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

Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (107 commits)
perf stat: Add more cache-miss percentage printouts
perf stat: Add -d -d and -d -d -d options to show more CPU events
ftrace/kbuild: Add recordmcount files to force full build
ftrace: Add self-tests for multiple function trace users
ftrace: Modify ftrace_set_filter/notrace to take ops
ftrace: Allow dynamically allocated function tracers
ftrace: Implement separate user function filtering
ftrace: Free hash with call_rcu_sched()
ftrace: Have global_ops store the functions that are to be traced
ftrace: Add ops parameter to ftrace_startup/shutdown functions
ftrace: Add enabled_functions file
ftrace: Use counters to enable functions to trace
ftrace: Separate hash allocation and assignment
ftrace: Create a global_ops to hold the filter and notrace hashes
ftrace: Use hash instead for FTRACE_FL_FILTER
ftrace: Replace FTRACE_FL_NOTRACE flag with a hash of ignored functions
perf bench, x86: Add alternatives-asm.h wrapper
x86, 64-bit: Fix copy_[to/from]_user() checks for the userspace address limit
x86, mem: memset_64.S: Optimize memset by enhanced REP MOVSB/STOSB
x86, mem: memmove_64.S: Optimize memmove by enhanced REP MOVSB/STOSB
...

+4088 -1775
+1
Makefile
··· 1268 1268 @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' 1269 1269 @echo ' make C=2 [targets] Force check of all c source with $$CHECK' 1270 1270 @echo ' make W=1 [targets] Enable extra gcc checks' 1271 + @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' 1271 1272 @echo '' 1272 1273 @echo 'Execute "make" or "make all" to build all targets marked with [*] ' 1273 1274 @echo 'For further info see the ./README file'
+12 -10
arch/mips/include/asm/jump_label.h
··· 20 20 #define WORD_INSN ".word" 21 21 #endif 22 22 23 - #define JUMP_LABEL(key, label) \ 24 - do { \ 25 - asm goto("1:\tnop\n\t" \ 26 - "nop\n\t" \ 27 - ".pushsection __jump_table, \"a\"\n\t" \ 28 - WORD_INSN " 1b, %l[" #label "], %0\n\t" \ 29 - ".popsection\n\t" \ 30 - : : "i" (key) : : label); \ 31 - } while (0) 32 - 23 + static __always_inline bool arch_static_branch(struct jump_label_key *key) 24 + { 25 + asm goto("1:\tnop\n\t" 26 + "nop\n\t" 27 + ".pushsection __jump_table, \"aw\"\n\t" 28 + WORD_INSN " 1b, %l[l_yes], %0\n\t" 29 + ".popsection\n\t" 30 + : : "i" (key) : : l_yes); 31 + return false; 32 + l_yes: 33 + return true; 34 + } 33 35 34 36 #endif /* __KERNEL__ */ 35 37
+1
arch/s390/Kconfig
··· 88 88 select HAVE_KERNEL_XZ 89 89 select HAVE_GET_USER_PAGES_FAST 90 90 select HAVE_ARCH_MUTEX_CPU_RELAX 91 + select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 91 92 select ARCH_INLINE_SPIN_TRYLOCK 92 93 select ARCH_INLINE_SPIN_TRYLOCK_BH 93 94 select ARCH_INLINE_SPIN_LOCK
+1 -3
arch/s390/include/asm/ftrace.h
··· 11 11 12 12 #ifdef CONFIG_64BIT 13 13 #define MCOUNT_INSN_SIZE 12 14 - #define MCOUNT_OFFSET 8 15 14 #else 16 15 #define MCOUNT_INSN_SIZE 20 17 - #define MCOUNT_OFFSET 4 18 16 #endif 19 17 20 18 static inline unsigned long ftrace_call_adjust(unsigned long addr) 21 19 { 22 - return addr - MCOUNT_OFFSET; 20 + return addr; 23 21 } 24 22 25 23 #endif /* __ASSEMBLY__ */
+37
arch/s390/include/asm/jump_label.h
··· 1 + #ifndef _ASM_S390_JUMP_LABEL_H 2 + #define _ASM_S390_JUMP_LABEL_H 3 + 4 + #include <linux/types.h> 5 + 6 + #define JUMP_LABEL_NOP_SIZE 6 7 + 8 + #ifdef CONFIG_64BIT 9 + #define ASM_PTR ".quad" 10 + #define ASM_ALIGN ".balign 8" 11 + #else 12 + #define ASM_PTR ".long" 13 + #define ASM_ALIGN ".balign 4" 14 + #endif 15 + 16 + static __always_inline bool arch_static_branch(struct jump_label_key *key) 17 + { 18 + asm goto("0: brcl 0,0\n" 19 + ".pushsection __jump_table, \"aw\"\n" 20 + ASM_ALIGN "\n" 21 + ASM_PTR " 0b, %l[label], %0\n" 22 + ".popsection\n" 23 + : : "X" (key) : : label); 24 + return false; 25 + label: 26 + return true; 27 + } 28 + 29 + typedef unsigned long jump_label_t; 30 + 31 + struct jump_entry { 32 + jump_label_t code; 33 + jump_label_t target; 34 + jump_label_t key; 35 + }; 36 + 37 + #endif
+1 -1
arch/s390/kernel/Makefile
··· 23 23 obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ 24 24 processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ 25 25 s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ 26 - vdso.o vtime.o sysinfo.o nmi.o sclp.o 26 + vdso.o vtime.o sysinfo.o nmi.o sclp.o jump_label.o 27 27 28 28 obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) 29 29 obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+59
arch/s390/kernel/jump_label.c
··· 1 + /* 2 + * Jump label s390 support 3 + * 4 + * Copyright IBM Corp. 2011 5 + * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> 6 + */ 7 + #include <linux/module.h> 8 + #include <linux/uaccess.h> 9 + #include <linux/stop_machine.h> 10 + #include <linux/jump_label.h> 11 + #include <asm/ipl.h> 12 + 13 + #ifdef HAVE_JUMP_LABEL 14 + 15 + struct insn { 16 + u16 opcode; 17 + s32 offset; 18 + } __packed; 19 + 20 + struct insn_args { 21 + unsigned long *target; 22 + struct insn *insn; 23 + ssize_t size; 24 + }; 25 + 26 + static int __arch_jump_label_transform(void *data) 27 + { 28 + struct insn_args *args = data; 29 + int rc; 30 + 31 + rc = probe_kernel_write(args->target, args->insn, args->size); 32 + WARN_ON_ONCE(rc < 0); 33 + return 0; 34 + } 35 + 36 + void arch_jump_label_transform(struct jump_entry *entry, 37 + enum jump_label_type type) 38 + { 39 + struct insn_args args; 40 + struct insn insn; 41 + 42 + if (type == JUMP_LABEL_ENABLE) { 43 + /* brcl 15,offset */ 44 + insn.opcode = 0xc0f4; 45 + insn.offset = (entry->target - entry->code) >> 1; 46 + } else { 47 + /* brcl 0,0 */ 48 + insn.opcode = 0xc004; 49 + insn.offset = 0; 50 + } 51 + 52 + args.target = (void *) entry->code; 53 + args.insn = &insn; 54 + args.size = JUMP_LABEL_NOP_SIZE; 55 + 56 + stop_machine(__arch_jump_label_transform, &args, NULL); 57 + } 58 + 59 + #endif
+14 -11
arch/sparc/include/asm/jump_label.h
··· 7 7 8 8 #define JUMP_LABEL_NOP_SIZE 4 9 9 10 - #define JUMP_LABEL(key, label) \ 11 - do { \ 12 - asm goto("1:\n\t" \ 13 - "nop\n\t" \ 14 - "nop\n\t" \ 15 - ".pushsection __jump_table, \"a\"\n\t"\ 16 - ".align 4\n\t" \ 17 - ".word 1b, %l[" #label "], %c0\n\t" \ 18 - ".popsection \n\t" \ 19 - : : "i" (key) : : label);\ 20 - } while (0) 10 + static __always_inline bool arch_static_branch(struct jump_label_key *key) 11 + { 12 + asm goto("1:\n\t" 13 + "nop\n\t" 14 + "nop\n\t" 15 + ".pushsection __jump_table, \"aw\"\n\t" 16 + ".align 4\n\t" 17 + ".word 1b, %l[l_yes], %c0\n\t" 18 + ".popsection \n\t" 19 + : : "i" (key) : : l_yes); 20 + return false; 21 + l_yes: 22 + return true; 23 + } 21 24 22 25 #endif /* __KERNEL__ */ 23 26
+9
arch/x86/include/asm/alternative-asm.h
··· 15 15 .endm 16 16 #endif 17 17 18 + .macro altinstruction_entry orig alt feature orig_len alt_len 19 + .align 8 20 + .quad \orig 21 + .quad \alt 22 + .word \feature 23 + .byte \orig_len 24 + .byte \alt_len 25 + .endm 26 + 18 27 #endif /* __ASSEMBLY__ */
+1 -2
arch/x86/include/asm/alternative.h
··· 4 4 #include <linux/types.h> 5 5 #include <linux/stddef.h> 6 6 #include <linux/stringify.h> 7 - #include <linux/jump_label.h> 8 7 #include <asm/asm.h> 9 8 10 9 /* ··· 190 191 extern void *text_poke_smp(void *addr, const void *opcode, size_t len); 191 192 extern void text_poke_smp_batch(struct text_poke_param *params, int n); 192 193 193 - #if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL) 194 + #if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_JUMP_LABEL) 194 195 #define IDEAL_NOP_SIZE_5 5 195 196 extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5]; 196 197 extern void arch_init_ideal_nop5(void);
+1
arch/x86/include/asm/cpufeature.h
··· 195 195 196 196 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ 197 197 #define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ 198 + #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */ 198 199 199 200 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 200 201
+3 -4
arch/x86/include/asm/ftrace.h
··· 38 38 static inline unsigned long ftrace_call_adjust(unsigned long addr) 39 39 { 40 40 /* 41 - * call mcount is "e8 <4 byte offset>" 42 - * The addr points to the 4 byte offset and the caller of this 43 - * function wants the pointer to e8. Simply subtract one. 41 + * addr is the address of the mcount call instruction. 42 + * recordmcount does the necessary offset calculation. 44 43 */ 45 - return addr - 1; 44 + return addr; 46 45 } 47 46 48 47 #ifdef CONFIG_DYNAMIC_FTRACE
+15 -10
arch/x86/include/asm/jump_label.h
··· 5 5 6 6 #include <linux/types.h> 7 7 #include <asm/nops.h> 8 + #include <asm/asm.h> 8 9 9 10 #define JUMP_LABEL_NOP_SIZE 5 10 11 11 - # define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" 12 + #define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" 12 13 13 - # define JUMP_LABEL(key, label) \ 14 - do { \ 15 - asm goto("1:" \ 16 - JUMP_LABEL_INITIAL_NOP \ 17 - ".pushsection __jump_table, \"aw\" \n\t"\ 18 - _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \ 19 - ".popsection \n\t" \ 20 - : : "i" (key) : : label); \ 21 - } while (0) 14 + static __always_inline bool arch_static_branch(struct jump_label_key *key) 15 + { 16 + asm goto("1:" 17 + JUMP_LABEL_INITIAL_NOP 18 + ".pushsection __jump_table, \"aw\" \n\t" 19 + _ASM_ALIGN "\n\t" 20 + _ASM_PTR "1b, %l[l_yes], %c0 \n\t" 21 + ".popsection \n\t" 22 + : : "i" (key) : : l_yes); 23 + return false; 24 + l_yes: 25 + return true; 26 + } 22 27 23 28 #endif /* __KERNEL__ */ 24 29
+1 -1
arch/x86/include/asm/setup.h
··· 88 88 * executable.) 89 89 */ 90 90 #define RESERVE_BRK(name,sz) \ 91 - static void __section(.discard.text) __used \ 91 + static void __section(.discard.text) __used notrace \ 92 92 __brk_reservation_fn_##name##__(void) { \ 93 93 asm volatile ( \ 94 94 ".pushsection .brk_reservation,\"aw\",@nobits;" \
-3
arch/x86/include/asm/stacktrace.h
··· 37 37 /* Generic stack tracer with callbacks */ 38 38 39 39 struct stacktrace_ops { 40 - void (*warning)(void *data, char *msg); 41 - /* msg must contain %s for the symbol */ 42 - void (*warning_symbol)(void *data, char *msg, unsigned long symbol); 43 40 void (*address)(void *data, unsigned long address, int reliable); 44 41 /* On negative return stop dumping */ 45 42 int (*stack)(void *data, char *name);
+1 -1
arch/x86/include/asm/uaccess.h
··· 42 42 * Returns 0 if the range is valid, nonzero otherwise. 43 43 * 44 44 * This is equivalent to the following test: 45 - * (u33)addr + (u33)size >= (u33)current->addr_limit.seg (u65 for x86_64) 45 + * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64) 46 46 * 47 47 * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... 48 48 */
+10 -1
arch/x86/kernel/alternative.c
··· 210 210 u8 insnbuf[MAX_PATCH_LEN]; 211 211 212 212 DPRINTK("%s: alt table %p -> %p\n", __func__, start, end); 213 + /* 214 + * The scan order should be from start to end. A later scanned 215 + * alternative code can overwrite a previous scanned alternative code. 216 + * Some kernel functions (e.g. memcpy, memset, etc) use this order to 217 + * patch code. 218 + * 219 + * So be careful if you want to change the scan order to any other 220 + * order. 221 + */ 213 222 for (a = start; a < end; a++) { 214 223 u8 *instr = a->instr; 215 224 BUG_ON(a->replacementlen > a->instrlen); ··· 688 679 __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL); 689 680 } 690 681 691 - #if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL) 682 + #if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_JUMP_LABEL) 692 683 693 684 #ifdef CONFIG_X86_64 694 685 unsigned char ideal_nop5[5] = { 0x66, 0x66, 0x66, 0x66, 0x90 };
+1 -2
arch/x86/kernel/cpu/common.c
··· 565 565 566 566 cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); 567 567 568 - if (eax > 0) 569 - c->x86_capability[9] = ebx; 568 + c->x86_capability[9] = ebx; 570 569 } 571 570 572 571 /* AMD-defined flags: level 0x80000001 */
+15 -4
arch/x86/kernel/cpu/intel.c
··· 29 29 30 30 static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) 31 31 { 32 + u64 misc_enable; 33 + 32 34 /* Unmask CPUID levels if masked: */ 33 35 if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { 34 - u64 misc_enable; 35 - 36 36 rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); 37 37 38 38 if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) { ··· 118 118 * (model 2) with the same problem. 119 119 */ 120 120 if (c->x86 == 15) { 121 - u64 misc_enable; 122 - 123 121 rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); 124 122 125 123 if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING) { ··· 128 130 } 129 131 } 130 132 #endif 133 + 134 + /* 135 + * If fast string is not enabled in IA32_MISC_ENABLE for any reason, 136 + * clear the fast string and enhanced fast string CPU capabilities. 137 + */ 138 + if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { 139 + rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); 140 + if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) { 141 + printk(KERN_INFO "Disabled fast string operations\n"); 142 + setup_clear_cpu_cap(X86_FEATURE_REP_GOOD); 143 + setup_clear_cpu_cap(X86_FEATURE_ERMS); 144 + } 145 + } 131 146 } 132 147 133 148 #ifdef CONFIG_X86_32
+11 -17
arch/x86/kernel/cpu/perf_event.c
··· 31 31 #include <asm/nmi.h> 32 32 #include <asm/compat.h> 33 33 #include <asm/smp.h> 34 + #include <asm/alternative.h> 34 35 35 36 #if 0 36 37 #undef wrmsrl ··· 364 363 return new_raw_count; 365 364 } 366 365 367 - /* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */ 368 366 static inline int x86_pmu_addr_offset(int index) 369 367 { 370 - if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) 371 - return index << 1; 372 - return index; 368 + int offset; 369 + 370 + /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */ 371 + alternative_io(ASM_NOP2, 372 + "shll $1, %%eax", 373 + X86_FEATURE_PERFCTR_CORE, 374 + "=a" (offset), 375 + "a" (index)); 376 + 377 + return offset; 373 378 } 374 379 375 380 static inline unsigned int x86_pmu_config_addr(int index) ··· 1773 1766 * callchain support 1774 1767 */ 1775 1768 1776 - static void 1777 - backtrace_warning_symbol(void *data, char *msg, unsigned long symbol) 1778 - { 1779 - /* Ignore warnings */ 1780 - } 1781 - 1782 - static void backtrace_warning(void *data, char *msg) 1783 - { 1784 - /* Ignore warnings */ 1785 - } 1786 - 1787 1769 static int backtrace_stack(void *data, char *name) 1788 1770 { 1789 1771 return 0; ··· 1786 1790 } 1787 1791 1788 1792 static const struct stacktrace_ops backtrace_ops = { 1789 - .warning = backtrace_warning, 1790 - .warning_symbol = backtrace_warning_symbol, 1791 1793 .stack = backtrace_stack, 1792 1794 .address = backtrace_address, 1793 1795 .walk_stack = print_context_stack_bp,
+8 -6
arch/x86/kernel/cpu/perf_event_amd.c
··· 96 96 */ 97 97 static const u64 amd_perfmon_event_map[] = 98 98 { 99 - [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, 100 - [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, 101 - [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, 102 - [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, 103 - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, 104 - [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, 99 + [PERF_COUNT_HW_CPU_CYCLES] = 0x0076, 100 + [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, 101 + [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, 102 + [PERF_COUNT_HW_CACHE_MISSES] = 0x0081, 103 + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, 104 + [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, 105 + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00d0, /* "Decoder empty" event */ 106 + [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x00d1, /* "Dispatch stalls" event */ 105 107 }; 106 108 107 109 static u64 amd_pmu_event_map(int hw_event)
+27 -10
arch/x86/kernel/cpu/perf_event_intel.c
··· 36 36 [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, 37 37 }; 38 38 39 - static struct event_constraint intel_core_event_constraints[] = 39 + static struct event_constraint intel_core_event_constraints[] __read_mostly = 40 40 { 41 41 INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ 42 42 INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ ··· 47 47 EVENT_CONSTRAINT_END 48 48 }; 49 49 50 - static struct event_constraint intel_core2_event_constraints[] = 50 + static struct event_constraint intel_core2_event_constraints[] __read_mostly = 51 51 { 52 52 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 53 53 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ ··· 70 70 EVENT_CONSTRAINT_END 71 71 }; 72 72 73 - static struct event_constraint intel_nehalem_event_constraints[] = 73 + static struct event_constraint intel_nehalem_event_constraints[] __read_mostly = 74 74 { 75 75 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 76 76 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ ··· 86 86 EVENT_CONSTRAINT_END 87 87 }; 88 88 89 - static struct extra_reg intel_nehalem_extra_regs[] = 89 + static struct extra_reg intel_nehalem_extra_regs[] __read_mostly = 90 90 { 91 91 INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff), 92 92 EVENT_EXTRA_END 93 93 }; 94 94 95 - static struct event_constraint intel_nehalem_percore_constraints[] = 95 + static struct event_constraint intel_nehalem_percore_constraints[] __read_mostly = 96 96 { 97 97 INTEL_EVENT_CONSTRAINT(0xb7, 0), 98 98 EVENT_CONSTRAINT_END 99 99 }; 100 100 101 - static struct event_constraint intel_westmere_event_constraints[] = 101 + static struct event_constraint intel_westmere_event_constraints[] __read_mostly = 102 102 { 103 103 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 104 104 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ ··· 110 110 EVENT_CONSTRAINT_END 111 111 }; 112 112 113 - static struct event_constraint intel_snb_event_constraints[] = 113 + static struct event_constraint intel_snb_event_constraints[] __read_mostly = 114 114 { 115 115 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 116 116 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ ··· 123 123 EVENT_CONSTRAINT_END 124 124 }; 125 125 126 - static struct extra_reg intel_westmere_extra_regs[] = 126 + static struct extra_reg intel_westmere_extra_regs[] __read_mostly = 127 127 { 128 128 INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff), 129 129 INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff), 130 130 EVENT_EXTRA_END 131 131 }; 132 132 133 - static struct event_constraint intel_westmere_percore_constraints[] = 133 + static struct event_constraint intel_westmere_percore_constraints[] __read_mostly = 134 134 { 135 135 INTEL_EVENT_CONSTRAINT(0xb7, 0), 136 136 INTEL_EVENT_CONSTRAINT(0xbb, 0), 137 137 EVENT_CONSTRAINT_END 138 138 }; 139 139 140 - static struct event_constraint intel_gen_event_constraints[] = 140 + static struct event_constraint intel_gen_event_constraints[] __read_mostly = 141 141 { 142 142 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ 143 143 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ ··· 1440 1440 x86_pmu.enable_all = intel_pmu_nhm_enable_all; 1441 1441 x86_pmu.extra_regs = intel_nehalem_extra_regs; 1442 1442 1443 + /* UOPS_ISSUED.STALLED_CYCLES */ 1444 + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; 1445 + /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */ 1446 + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1; 1447 + 1443 1448 if (ebx & 0x40) { 1444 1449 /* 1445 1450 * Erratum AAJ80 detected, we work it around by using ··· 1485 1480 x86_pmu.enable_all = intel_pmu_nhm_enable_all; 1486 1481 x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints; 1487 1482 x86_pmu.extra_regs = intel_westmere_extra_regs; 1483 + 1484 + /* UOPS_ISSUED.STALLED_CYCLES */ 1485 + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; 1486 + /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */ 1487 + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1; 1488 + 1488 1489 pr_cont("Westmere events, "); 1489 1490 break; 1490 1491 ··· 1502 1491 1503 1492 x86_pmu.event_constraints = intel_snb_event_constraints; 1504 1493 x86_pmu.pebs_constraints = intel_snb_pebs_events; 1494 + 1495 + /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ 1496 + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; 1497 + /* UOPS_DISPATCHED.THREAD,c=1,i=1 to count stall cycles*/ 1498 + intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x18001b1; 1499 + 1505 1500 pr_cont("SandyBridge events, "); 1506 1501 break; 1507 1502
+3 -4
arch/x86/kernel/cpu/perf_event_p4.c
··· 468 468 .opcode = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED), 469 469 .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, 470 470 .escr_emask = 471 - P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS), 471 + P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS), 472 472 .cntr = { {12, 13, 16}, {14, 15, 17} }, 473 473 }, 474 474 [P4_EVENT_X87_ASSIST] = { ··· 912 912 int idx, handled = 0; 913 913 u64 val; 914 914 915 - data.addr = 0; 916 - data.raw = NULL; 915 + perf_sample_data_init(&data, 0); 917 916 918 917 cpuc = &__get_cpu_var(cpu_hw_events); 919 918 ··· 1196 1197 { 1197 1198 unsigned int low, high; 1198 1199 1199 - /* If we get stripped -- indexig fails */ 1200 + /* If we get stripped -- indexing fails */ 1200 1201 BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC); 1201 1202 1202 1203 rdmsr(MSR_IA32_MISC_ENABLE, low, high);
-16
arch/x86/kernel/dumpstack.c
··· 135 135 } 136 136 EXPORT_SYMBOL_GPL(print_context_stack_bp); 137 137 138 - 139 - static void 140 - print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) 141 - { 142 - printk(data); 143 - print_symbol(msg, symbol); 144 - printk("\n"); 145 - } 146 - 147 - static void print_trace_warning(void *data, char *msg) 148 - { 149 - printk("%s%s\n", (char *)data, msg); 150 - } 151 - 152 138 static int print_trace_stack(void *data, char *name) 153 139 { 154 140 printk("%s <%s> ", (char *)data, name); ··· 152 166 } 153 167 154 168 static const struct stacktrace_ops print_trace_ops = { 155 - .warning = print_trace_warning, 156 - .warning_symbol = print_trace_warning_symbol, 157 169 .stack = print_trace_stack, 158 170 .address = print_trace_address, 159 171 .walk_stack = print_context_stack,
+1
arch/x86/kernel/module.c
··· 24 24 #include <linux/bug.h> 25 25 #include <linux/mm.h> 26 26 #include <linux/gfp.h> 27 + #include <linux/jump_label.h> 27 28 28 29 #include <asm/system.h> 29 30 #include <asm/page.h>
-13
arch/x86/kernel/stacktrace.c
··· 9 9 #include <linux/uaccess.h> 10 10 #include <asm/stacktrace.h> 11 11 12 - static void save_stack_warning(void *data, char *msg) 13 - { 14 - } 15 - 16 - static void 17 - save_stack_warning_symbol(void *data, char *msg, unsigned long symbol) 18 - { 19 - } 20 - 21 12 static int save_stack_stack(void *data, char *name) 22 13 { 23 14 return 0; ··· 44 53 } 45 54 46 55 static const struct stacktrace_ops save_stack_ops = { 47 - .warning = save_stack_warning, 48 - .warning_symbol = save_stack_warning_symbol, 49 56 .stack = save_stack_stack, 50 57 .address = save_stack_address, 51 58 .walk_stack = print_context_stack, 52 59 }; 53 60 54 61 static const struct stacktrace_ops save_stack_ops_nosched = { 55 - .warning = save_stack_warning, 56 - .warning_symbol = save_stack_warning_symbol, 57 62 .stack = save_stack_stack, 58 63 .address = save_stack_address_nosched, 59 64 .walk_stack = print_context_stack,
+24 -9
arch/x86/lib/clear_page_64.S
··· 1 1 #include <linux/linkage.h> 2 2 #include <asm/dwarf2.h> 3 + #include <asm/alternative-asm.h> 3 4 4 5 /* 5 6 * Zero a page. ··· 14 13 ret 15 14 CFI_ENDPROC 16 15 ENDPROC(clear_page_c) 16 + 17 + ENTRY(clear_page_c_e) 18 + CFI_STARTPROC 19 + movl $4096,%ecx 20 + xorl %eax,%eax 21 + rep stosb 22 + ret 23 + CFI_ENDPROC 24 + ENDPROC(clear_page_c_e) 17 25 18 26 ENTRY(clear_page) 19 27 CFI_STARTPROC ··· 48 38 .Lclear_page_end: 49 39 ENDPROC(clear_page) 50 40 51 - /* Some CPUs run faster using the string instructions. 52 - It is also a lot simpler. Use this when possible */ 41 + /* 42 + * Some CPUs support enhanced REP MOVSB/STOSB instructions. 43 + * It is recommended to use this when possible. 44 + * If enhanced REP MOVSB/STOSB is not available, try to use fast string. 45 + * Otherwise, use original function. 46 + * 47 + */ 53 48 54 49 #include <asm/cpufeature.h> 55 50 56 51 .section .altinstr_replacement,"ax" 57 52 1: .byte 0xeb /* jmp <disp8> */ 58 53 .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */ 59 - 2: 54 + 2: .byte 0xeb /* jmp <disp8> */ 55 + .byte (clear_page_c_e - clear_page) - (3f - 2b) /* offset */ 56 + 3: 60 57 .previous 61 58 .section .altinstructions,"a" 62 - .align 8 63 - .quad clear_page 64 - .quad 1b 65 - .word X86_FEATURE_REP_GOOD 66 - .byte .Lclear_page_end - clear_page 67 - .byte 2b - 1b 59 + altinstruction_entry clear_page,1b,X86_FEATURE_REP_GOOD,\ 60 + .Lclear_page_end-clear_page, 2b-1b 61 + altinstruction_entry clear_page,2b,X86_FEATURE_ERMS, \ 62 + .Lclear_page_end-clear_page,3b-2b 68 63 .previous
+57 -12
arch/x86/lib/copy_user_64.S
··· 15 15 #include <asm/asm-offsets.h> 16 16 #include <asm/thread_info.h> 17 17 #include <asm/cpufeature.h> 18 + #include <asm/alternative-asm.h> 18 19 19 - .macro ALTERNATIVE_JUMP feature,orig,alt 20 + /* 21 + * By placing feature2 after feature1 in altinstructions section, we logically 22 + * implement: 23 + * If CPU has feature2, jmp to alt2 is used 24 + * else if CPU has feature1, jmp to alt1 is used 25 + * else jmp to orig is used. 26 + */ 27 + .macro ALTERNATIVE_JUMP feature1,feature2,orig,alt1,alt2 20 28 0: 21 29 .byte 0xe9 /* 32bit jump */ 22 30 .long \orig-1f /* by default jump to orig */ 23 31 1: 24 32 .section .altinstr_replacement,"ax" 25 33 2: .byte 0xe9 /* near jump with 32bit immediate */ 26 - .long \alt-1b /* offset */ /* or alternatively to alt */ 34 + .long \alt1-1b /* offset */ /* or alternatively to alt1 */ 35 + 3: .byte 0xe9 /* near jump with 32bit immediate */ 36 + .long \alt2-1b /* offset */ /* or alternatively to alt2 */ 27 37 .previous 38 + 28 39 .section .altinstructions,"a" 29 - .align 8 30 - .quad 0b 31 - .quad 2b 32 - .word \feature /* when feature is set */ 33 - .byte 5 34 - .byte 5 40 + altinstruction_entry 0b,2b,\feature1,5,5 41 + altinstruction_entry 0b,3b,\feature2,5,5 35 42 .previous 36 43 .endm 37 44 ··· 79 72 addq %rdx,%rcx 80 73 jc bad_to_user 81 74 cmpq TI_addr_limit(%rax),%rcx 82 - jae bad_to_user 83 - ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string 75 + ja bad_to_user 76 + ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \ 77 + copy_user_generic_unrolled,copy_user_generic_string, \ 78 + copy_user_enhanced_fast_string 84 79 CFI_ENDPROC 85 80 ENDPROC(_copy_to_user) 86 81 ··· 94 85 addq %rdx,%rcx 95 86 jc bad_from_user 96 87 cmpq TI_addr_limit(%rax),%rcx 97 - jae bad_from_user 98 - ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string 88 + ja bad_from_user 89 + ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \ 90 + copy_user_generic_unrolled,copy_user_generic_string, \ 91 + copy_user_enhanced_fast_string 99 92 CFI_ENDPROC 100 93 ENDPROC(_copy_from_user) 101 94 ··· 266 255 .previous 267 256 CFI_ENDPROC 268 257 ENDPROC(copy_user_generic_string) 258 + 259 + /* 260 + * Some CPUs are adding enhanced REP MOVSB/STOSB instructions. 261 + * It's recommended to use enhanced REP MOVSB/STOSB if it's enabled. 262 + * 263 + * Input: 264 + * rdi destination 265 + * rsi source 266 + * rdx count 267 + * 268 + * Output: 269 + * eax uncopied bytes or 0 if successful. 270 + */ 271 + ENTRY(copy_user_enhanced_fast_string) 272 + CFI_STARTPROC 273 + andl %edx,%edx 274 + jz 2f 275 + movl %edx,%ecx 276 + 1: rep 277 + movsb 278 + 2: xorl %eax,%eax 279 + ret 280 + 281 + .section .fixup,"ax" 282 + 12: movl %ecx,%edx /* ecx is zerorest also */ 283 + jmp copy_user_handle_tail 284 + .previous 285 + 286 + .section __ex_table,"a" 287 + .align 8 288 + .quad 1b,12b 289 + .previous 290 + CFI_ENDPROC 291 + ENDPROC(copy_user_enhanced_fast_string)
+32 -13
arch/x86/lib/memcpy_64.S
··· 4 4 5 5 #include <asm/cpufeature.h> 6 6 #include <asm/dwarf2.h> 7 + #include <asm/alternative-asm.h> 7 8 8 9 /* 9 10 * memcpy - Copy a memory block. ··· 36 35 rep movsb 37 36 ret 38 37 .Lmemcpy_e: 38 + .previous 39 + 40 + /* 41 + * memcpy_c_e() - enhanced fast string memcpy. This is faster and simpler than 42 + * memcpy_c. Use memcpy_c_e when possible. 43 + * 44 + * This gets patched over the unrolled variant (below) via the 45 + * alternative instructions framework: 46 + */ 47 + .section .altinstr_replacement, "ax", @progbits 48 + .Lmemcpy_c_e: 49 + movq %rdi, %rax 50 + 51 + movl %edx, %ecx 52 + rep movsb 53 + ret 54 + .Lmemcpy_e_e: 39 55 .previous 40 56 41 57 ENTRY(__memcpy) ··· 189 171 ENDPROC(__memcpy) 190 172 191 173 /* 192 - * Some CPUs run faster using the string copy instructions. 193 - * It is also a lot simpler. Use this when possible: 194 - */ 195 - 196 - .section .altinstructions, "a" 197 - .align 8 198 - .quad memcpy 199 - .quad .Lmemcpy_c 200 - .word X86_FEATURE_REP_GOOD 201 - 202 - /* 174 + * Some CPUs are adding enhanced REP MOVSB/STOSB feature 175 + * If the feature is supported, memcpy_c_e() is the first choice. 176 + * If enhanced rep movsb copy is not available, use fast string copy 177 + * memcpy_c() when possible. This is faster and code is simpler than 178 + * original memcpy(). 179 + * Otherwise, original memcpy() is used. 180 + * In .altinstructions section, ERMS feature is placed after REG_GOOD 181 + * feature to implement the right patch order. 182 + * 203 183 * Replace only beginning, memcpy is used to apply alternatives, 204 184 * so it is silly to overwrite itself with nops - reboot is the 205 185 * only outcome... 206 186 */ 207 - .byte .Lmemcpy_e - .Lmemcpy_c 208 - .byte .Lmemcpy_e - .Lmemcpy_c 187 + .section .altinstructions, "a" 188 + altinstruction_entry memcpy,.Lmemcpy_c,X86_FEATURE_REP_GOOD,\ 189 + .Lmemcpy_e-.Lmemcpy_c,.Lmemcpy_e-.Lmemcpy_c 190 + altinstruction_entry memcpy,.Lmemcpy_c_e,X86_FEATURE_ERMS, \ 191 + .Lmemcpy_e_e-.Lmemcpy_c_e,.Lmemcpy_e_e-.Lmemcpy_c_e 209 192 .previous
+28 -1
arch/x86/lib/memmove_64.S
··· 8 8 #define _STRING_C 9 9 #include <linux/linkage.h> 10 10 #include <asm/dwarf2.h> 11 + #include <asm/cpufeature.h> 11 12 12 13 #undef memmove 13 14 ··· 25 24 */ 26 25 ENTRY(memmove) 27 26 CFI_STARTPROC 27 + 28 28 /* Handle more 32bytes in loop */ 29 29 mov %rdi, %rax 30 30 cmp $0x20, %rdx ··· 33 31 34 32 /* Decide forward/backward copy mode */ 35 33 cmp %rdi, %rsi 36 - jb 2f 34 + jge .Lmemmove_begin_forward 35 + mov %rsi, %r8 36 + add %rdx, %r8 37 + cmp %rdi, %r8 38 + jg 2f 37 39 40 + .Lmemmove_begin_forward: 38 41 /* 39 42 * movsq instruction have many startup latency 40 43 * so we handle small size by general register. ··· 85 78 rep movsq 86 79 movq %r11, (%r10) 87 80 jmp 13f 81 + .Lmemmove_end_forward: 82 + 88 83 /* 89 84 * Handle data backward by movsq. 90 85 */ ··· 203 194 13: 204 195 retq 205 196 CFI_ENDPROC 197 + 198 + .section .altinstr_replacement,"ax" 199 + .Lmemmove_begin_forward_efs: 200 + /* Forward moving data. */ 201 + movq %rdx, %rcx 202 + rep movsb 203 + retq 204 + .Lmemmove_end_forward_efs: 205 + .previous 206 + 207 + .section .altinstructions,"a" 208 + .align 8 209 + .quad .Lmemmove_begin_forward 210 + .quad .Lmemmove_begin_forward_efs 211 + .word X86_FEATURE_ERMS 212 + .byte .Lmemmove_end_forward-.Lmemmove_begin_forward 213 + .byte .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs 214 + .previous 206 215 ENDPROC(memmove)
+42 -12
arch/x86/lib/memset_64.S
··· 2 2 3 3 #include <linux/linkage.h> 4 4 #include <asm/dwarf2.h> 5 + #include <asm/cpufeature.h> 6 + #include <asm/alternative-asm.h> 5 7 6 8 /* 7 - * ISO C memset - set a memory block to a byte value. 9 + * ISO C memset - set a memory block to a byte value. This function uses fast 10 + * string to get better performance than the original function. The code is 11 + * simpler and shorter than the orignal function as well. 8 12 * 9 13 * rdi destination 10 14 * rsi value (char) ··· 33 29 movq %r9,%rax 34 30 ret 35 31 .Lmemset_e: 32 + .previous 33 + 34 + /* 35 + * ISO C memset - set a memory block to a byte value. This function uses 36 + * enhanced rep stosb to override the fast string function. 37 + * The code is simpler and shorter than the fast string function as well. 38 + * 39 + * rdi destination 40 + * rsi value (char) 41 + * rdx count (bytes) 42 + * 43 + * rax original destination 44 + */ 45 + .section .altinstr_replacement, "ax", @progbits 46 + .Lmemset_c_e: 47 + movq %rdi,%r9 48 + movb %sil,%al 49 + movl %edx,%ecx 50 + rep stosb 51 + movq %r9,%rax 52 + ret 53 + .Lmemset_e_e: 36 54 .previous 37 55 38 56 ENTRY(memset) ··· 138 112 ENDPROC(memset) 139 113 ENDPROC(__memset) 140 114 141 - /* Some CPUs run faster using the string instructions. 142 - It is also a lot simpler. Use this when possible */ 143 - 144 - #include <asm/cpufeature.h> 145 - 115 + /* Some CPUs support enhanced REP MOVSB/STOSB feature. 116 + * It is recommended to use this when possible. 117 + * 118 + * If enhanced REP MOVSB/STOSB feature is not available, use fast string 119 + * instructions. 120 + * 121 + * Otherwise, use original memset function. 122 + * 123 + * In .altinstructions section, ERMS feature is placed after REG_GOOD 124 + * feature to implement the right patch order. 125 + */ 146 126 .section .altinstructions,"a" 147 - .align 8 148 - .quad memset 149 - .quad .Lmemset_c 150 - .word X86_FEATURE_REP_GOOD 151 - .byte .Lfinal - memset 152 - .byte .Lmemset_e - .Lmemset_c 127 + altinstruction_entry memset,.Lmemset_c,X86_FEATURE_REP_GOOD,\ 128 + .Lfinal-memset,.Lmemset_e-.Lmemset_c 129 + altinstruction_entry memset,.Lmemset_c_e,X86_FEATURE_ERMS, \ 130 + .Lfinal-memset,.Lmemset_e_e-.Lmemset_c_e 153 131 .previous
-13
arch/x86/oprofile/backtrace.c
··· 16 16 #include <asm/stacktrace.h> 17 17 #include <linux/compat.h> 18 18 19 - static void backtrace_warning_symbol(void *data, char *msg, 20 - unsigned long symbol) 21 - { 22 - /* Ignore warnings */ 23 - } 24 - 25 - static void backtrace_warning(void *data, char *msg) 26 - { 27 - /* Ignore warnings */ 28 - } 29 - 30 19 static int backtrace_stack(void *data, char *name) 31 20 { 32 21 /* Yes, we want all stacks */ ··· 31 42 } 32 43 33 44 static struct stacktrace_ops backtrace_ops = { 34 - .warning = backtrace_warning, 35 - .warning_symbol = backtrace_warning_symbol, 36 45 .stack = backtrace_stack, 37 46 .address = backtrace_address, 38 47 .walk_stack = print_context_stack,
+4 -10
include/asm-generic/vmlinux.lds.h
··· 170 170 STRUCT_ALIGN(); \ 171 171 *(__tracepoints) \ 172 172 /* implement dynamic printk debug */ \ 173 + . = ALIGN(8); \ 174 + VMLINUX_SYMBOL(__start___jump_table) = .; \ 175 + *(__jump_table) \ 176 + VMLINUX_SYMBOL(__stop___jump_table) = .; \ 173 177 . = ALIGN(8); \ 174 178 VMLINUX_SYMBOL(__start___verbose) = .; \ 175 179 *(__verbose) \ ··· 231 227 } \ 232 228 \ 233 229 BUG_TABLE \ 234 - \ 235 - JUMP_TABLE \ 236 230 \ 237 231 /* PCI quirks */ \ 238 232 .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ ··· 590 588 #else 591 589 #define BUG_TABLE 592 590 #endif 593 - 594 - #define JUMP_TABLE \ 595 - . = ALIGN(8); \ 596 - __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) { \ 597 - VMLINUX_SYMBOL(__start___jump_table) = .; \ 598 - *(__jump_table) \ 599 - VMLINUX_SYMBOL(__stop___jump_table) = .; \ 600 - } 601 591 602 592 #ifdef CONFIG_PM_TRACE 603 593 #define TRACEDATA \
-2
include/linux/dynamic_debug.h
··· 1 1 #ifndef _DYNAMIC_DEBUG_H 2 2 #define _DYNAMIC_DEBUG_H 3 3 4 - #include <linux/jump_label.h> 5 - 6 4 /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which 7 5 * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They 8 6 * use independent hash functions, to reduce the chance of false positives.
+26 -9
include/linux/ftrace.h
··· 29 29 30 30 typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip); 31 31 32 + struct ftrace_hash; 33 + 34 + enum { 35 + FTRACE_OPS_FL_ENABLED = 1 << 0, 36 + FTRACE_OPS_FL_GLOBAL = 1 << 1, 37 + FTRACE_OPS_FL_DYNAMIC = 1 << 2, 38 + }; 39 + 32 40 struct ftrace_ops { 33 - ftrace_func_t func; 34 - struct ftrace_ops *next; 41 + ftrace_func_t func; 42 + struct ftrace_ops *next; 43 + unsigned long flags; 44 + #ifdef CONFIG_DYNAMIC_FTRACE 45 + struct ftrace_hash *notrace_hash; 46 + struct ftrace_hash *filter_hash; 47 + #endif 35 48 }; 36 49 37 50 extern int function_trace_stop; ··· 159 146 extern int ftrace_text_reserved(void *start, void *end); 160 147 161 148 enum { 162 - FTRACE_FL_FREE = (1 << 0), 163 - FTRACE_FL_FAILED = (1 << 1), 164 - FTRACE_FL_FILTER = (1 << 2), 165 - FTRACE_FL_ENABLED = (1 << 3), 166 - FTRACE_FL_NOTRACE = (1 << 4), 167 - FTRACE_FL_CONVERTED = (1 << 5), 149 + FTRACE_FL_ENABLED = (1 << 30), 150 + FTRACE_FL_FREE = (1 << 31), 168 151 }; 152 + 153 + #define FTRACE_FL_MASK (0x3UL << 30) 154 + #define FTRACE_REF_MAX ((1 << 30) - 1) 169 155 170 156 struct dyn_ftrace { 171 157 union { ··· 179 167 }; 180 168 181 169 int ftrace_force_update(void); 182 - void ftrace_set_filter(unsigned char *buf, int len, int reset); 170 + void ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, 171 + int len, int reset); 172 + void ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, 173 + int len, int reset); 174 + void ftrace_set_global_filter(unsigned char *buf, int len, int reset); 175 + void ftrace_set_global_notrace(unsigned char *buf, int len, int reset); 183 176 184 177 int register_ftrace_command(struct ftrace_func_command *cmd); 185 178 int unregister_ftrace_command(struct ftrace_func_command *cmd);
+7 -7
include/linux/init.h
··· 79 79 #define __exitused __used 80 80 #endif 81 81 82 - #define __exit __section(.exit.text) __exitused __cold 82 + #define __exit __section(.exit.text) __exitused __cold notrace 83 83 84 84 /* Used for HOTPLUG */ 85 - #define __devinit __section(.devinit.text) __cold 85 + #define __devinit __section(.devinit.text) __cold notrace 86 86 #define __devinitdata __section(.devinit.data) 87 87 #define __devinitconst __section(.devinit.rodata) 88 - #define __devexit __section(.devexit.text) __exitused __cold 88 + #define __devexit __section(.devexit.text) __exitused __cold notrace 89 89 #define __devexitdata __section(.devexit.data) 90 90 #define __devexitconst __section(.devexit.rodata) 91 91 92 92 /* Used for HOTPLUG_CPU */ 93 - #define __cpuinit __section(.cpuinit.text) __cold 93 + #define __cpuinit __section(.cpuinit.text) __cold notrace 94 94 #define __cpuinitdata __section(.cpuinit.data) 95 95 #define __cpuinitconst __section(.cpuinit.rodata) 96 - #define __cpuexit __section(.cpuexit.text) __exitused __cold 96 + #define __cpuexit __section(.cpuexit.text) __exitused __cold notrace 97 97 #define __cpuexitdata __section(.cpuexit.data) 98 98 #define __cpuexitconst __section(.cpuexit.rodata) 99 99 100 100 /* Used for MEMORY_HOTPLUG */ 101 - #define __meminit __section(.meminit.text) __cold 101 + #define __meminit __section(.meminit.text) __cold notrace 102 102 #define __meminitdata __section(.meminit.data) 103 103 #define __meminitconst __section(.meminit.rodata) 104 - #define __memexit __section(.memexit.text) __exitused __cold 104 + #define __memexit __section(.memexit.text) __exitused __cold notrace 105 105 #define __memexitdata __section(.memexit.data) 106 106 #define __memexitconst __section(.memexit.rodata) 107 107
+57 -34
include/linux/jump_label.h
··· 1 1 #ifndef _LINUX_JUMP_LABEL_H 2 2 #define _LINUX_JUMP_LABEL_H 3 3 4 + #include <linux/types.h> 5 + #include <linux/compiler.h> 6 + 4 7 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL) 8 + 9 + struct jump_label_key { 10 + atomic_t enabled; 11 + struct jump_entry *entries; 12 + #ifdef CONFIG_MODULES 13 + struct jump_label_mod *next; 14 + #endif 15 + }; 16 + 5 17 # include <asm/jump_label.h> 6 18 # define HAVE_JUMP_LABEL 7 19 #endif 8 20 9 21 enum jump_label_type { 22 + JUMP_LABEL_DISABLE = 0, 10 23 JUMP_LABEL_ENABLE, 11 - JUMP_LABEL_DISABLE 12 24 }; 13 25 14 26 struct module; 15 27 16 28 #ifdef HAVE_JUMP_LABEL 29 + 30 + #ifdef CONFIG_MODULES 31 + #define JUMP_LABEL_INIT {{ 0 }, NULL, NULL} 32 + #else 33 + #define JUMP_LABEL_INIT {{ 0 }, NULL} 34 + #endif 35 + 36 + static __always_inline bool static_branch(struct jump_label_key *key) 37 + { 38 + return arch_static_branch(key); 39 + } 17 40 18 41 extern struct jump_entry __start___jump_table[]; 19 42 extern struct jump_entry __stop___jump_table[]; ··· 46 23 extern void arch_jump_label_transform(struct jump_entry *entry, 47 24 enum jump_label_type type); 48 25 extern void arch_jump_label_text_poke_early(jump_label_t addr); 49 - extern void jump_label_update(unsigned long key, enum jump_label_type type); 50 - extern void jump_label_apply_nops(struct module *mod); 51 26 extern int jump_label_text_reserved(void *start, void *end); 52 - 53 - #define jump_label_enable(key) \ 54 - jump_label_update((unsigned long)key, JUMP_LABEL_ENABLE); 55 - 56 - #define jump_label_disable(key) \ 57 - jump_label_update((unsigned long)key, JUMP_LABEL_DISABLE); 27 + extern void jump_label_inc(struct jump_label_key *key); 28 + extern void jump_label_dec(struct jump_label_key *key); 29 + extern bool jump_label_enabled(struct jump_label_key *key); 30 + extern void jump_label_apply_nops(struct module *mod); 58 31 59 32 #else 60 33 61 - #define JUMP_LABEL(key, label) \ 62 - do { \ 63 - if (unlikely(*key)) \ 64 - goto label; \ 65 - } while (0) 34 + #include <asm/atomic.h> 66 35 67 - #define jump_label_enable(cond_var) \ 68 - do { \ 69 - *(cond_var) = 1; \ 70 - } while (0) 36 + #define JUMP_LABEL_INIT {ATOMIC_INIT(0)} 71 37 72 - #define jump_label_disable(cond_var) \ 73 - do { \ 74 - *(cond_var) = 0; \ 75 - } while (0) 38 + struct jump_label_key { 39 + atomic_t enabled; 40 + }; 76 41 77 - static inline int jump_label_apply_nops(struct module *mod) 42 + static __always_inline bool static_branch(struct jump_label_key *key) 78 43 { 79 - return 0; 44 + if (unlikely(atomic_read(&key->enabled))) 45 + return true; 46 + return false; 47 + } 48 + 49 + static inline void jump_label_inc(struct jump_label_key *key) 50 + { 51 + atomic_inc(&key->enabled); 52 + } 53 + 54 + static inline void jump_label_dec(struct jump_label_key *key) 55 + { 56 + atomic_dec(&key->enabled); 80 57 } 81 58 82 59 static inline int jump_label_text_reserved(void *start, void *end) ··· 87 64 static inline void jump_label_lock(void) {} 88 65 static inline void jump_label_unlock(void) {} 89 66 90 - #endif 67 + static inline bool jump_label_enabled(struct jump_label_key *key) 68 + { 69 + return !!atomic_read(&key->enabled); 70 + } 91 71 92 - #define COND_STMT(key, stmt) \ 93 - do { \ 94 - __label__ jl_enabled; \ 95 - JUMP_LABEL(key, jl_enabled); \ 96 - if (0) { \ 97 - jl_enabled: \ 98 - stmt; \ 99 - } \ 100 - } while (0) 72 + static inline int jump_label_apply_nops(struct module *mod) 73 + { 74 + return 0; 75 + } 76 + 77 + #endif 101 78 102 79 #endif
-44
include/linux/jump_label_ref.h
··· 1 - #ifndef _LINUX_JUMP_LABEL_REF_H 2 - #define _LINUX_JUMP_LABEL_REF_H 3 - 4 - #include <linux/jump_label.h> 5 - #include <asm/atomic.h> 6 - 7 - #ifdef HAVE_JUMP_LABEL 8 - 9 - static inline void jump_label_inc(atomic_t *key) 10 - { 11 - if (atomic_add_return(1, key) == 1) 12 - jump_label_enable(key); 13 - } 14 - 15 - static inline void jump_label_dec(atomic_t *key) 16 - { 17 - if (atomic_dec_and_test(key)) 18 - jump_label_disable(key); 19 - } 20 - 21 - #else /* !HAVE_JUMP_LABEL */ 22 - 23 - static inline void jump_label_inc(atomic_t *key) 24 - { 25 - atomic_inc(key); 26 - } 27 - 28 - static inline void jump_label_dec(atomic_t *key) 29 - { 30 - atomic_dec(key); 31 - } 32 - 33 - #undef JUMP_LABEL 34 - #define JUMP_LABEL(key, label) \ 35 - do { \ 36 - if (unlikely(__builtin_choose_expr( \ 37 - __builtin_types_compatible_p(typeof(key), atomic_t *), \ 38 - atomic_read((atomic_t *)(key)), *(key)))) \ 39 - goto label; \ 40 - } while (0) 41 - 42 - #endif /* HAVE_JUMP_LABEL */ 43 - 44 - #endif /* _LINUX_JUMP_LABEL_REF_H */
+1
include/linux/kernel.h
··· 283 283 extern unsigned long long memparse(const char *ptr, char **retptr); 284 284 285 285 extern int core_kernel_text(unsigned long addr); 286 + extern int core_kernel_data(unsigned long addr); 286 287 extern int __kernel_text_address(unsigned long addr); 287 288 extern int kernel_text_address(unsigned long addr); 288 289 extern int func_ptr_is_kernel_text(void *ptr);
+57 -64
include/linux/perf_event.h
··· 2 2 * Performance events: 3 3 * 4 4 * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de> 5 - * Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar 6 - * Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra 5 + * Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar 6 + * Copyright (C) 2008-2011, Red Hat, Inc., Peter Zijlstra 7 7 * 8 8 * Data type definitions, declarations, prototypes. 9 9 * ··· 52 52 PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4, 53 53 PERF_COUNT_HW_BRANCH_MISSES = 5, 54 54 PERF_COUNT_HW_BUS_CYCLES = 6, 55 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7, 56 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8, 55 57 56 58 PERF_COUNT_HW_MAX, /* non-ABI */ 57 59 }; ··· 470 468 PERF_CONTEXT_MAX = (__u64)-4095, 471 469 }; 472 470 473 - #define PERF_FLAG_FD_NO_GROUP (1U << 0) 474 - #define PERF_FLAG_FD_OUTPUT (1U << 1) 475 - #define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */ 471 + #define PERF_FLAG_FD_NO_GROUP (1U << 0) 472 + #define PERF_FLAG_FD_OUTPUT (1U << 1) 473 + #define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */ 476 474 477 475 #ifdef __KERNEL__ 478 476 /* ··· 486 484 #endif 487 485 488 486 struct perf_guest_info_callbacks { 489 - int (*is_in_guest) (void); 490 - int (*is_user_mode) (void); 491 - unsigned long (*get_guest_ip) (void); 487 + int (*is_in_guest)(void); 488 + int (*is_user_mode)(void); 489 + unsigned long (*get_guest_ip)(void); 492 490 }; 493 491 494 492 #ifdef CONFIG_HAVE_HW_BREAKPOINT ··· 507 505 #include <linux/ftrace.h> 508 506 #include <linux/cpu.h> 509 507 #include <linux/irq_work.h> 510 - #include <linux/jump_label_ref.h> 508 + #include <linux/jump_label.h> 511 509 #include <asm/atomic.h> 512 510 #include <asm/local.h> 513 511 ··· 654 652 * Start the transaction, after this ->add() doesn't need to 655 653 * do schedulability tests. 656 654 */ 657 - void (*start_txn) (struct pmu *pmu); /* optional */ 655 + void (*start_txn) (struct pmu *pmu); /* optional */ 658 656 /* 659 657 * If ->start_txn() disabled the ->add() schedulability test 660 658 * then ->commit_txn() is required to perform one. On success 661 659 * the transaction is closed. On error the transaction is kept 662 660 * open until ->cancel_txn() is called. 663 661 */ 664 - int (*commit_txn) (struct pmu *pmu); /* optional */ 662 + int (*commit_txn) (struct pmu *pmu); /* optional */ 665 663 /* 666 664 * Will cancel the transaction, assumes ->del() is called 667 665 * for each successful ->add() during the transaction. 668 666 */ 669 - void (*cancel_txn) (struct pmu *pmu); /* optional */ 667 + void (*cancel_txn) (struct pmu *pmu); /* optional */ 670 668 }; 671 669 672 670 /** ··· 714 712 struct pt_regs *regs); 715 713 716 714 enum perf_group_flag { 717 - PERF_GROUP_SOFTWARE = 0x1, 715 + PERF_GROUP_SOFTWARE = 0x1, 718 716 }; 719 717 720 - #define SWEVENT_HLIST_BITS 8 721 - #define SWEVENT_HLIST_SIZE (1 << SWEVENT_HLIST_BITS) 718 + #define SWEVENT_HLIST_BITS 8 719 + #define SWEVENT_HLIST_SIZE (1 << SWEVENT_HLIST_BITS) 722 720 723 721 struct swevent_hlist { 724 - struct hlist_head heads[SWEVENT_HLIST_SIZE]; 725 - struct rcu_head rcu_head; 722 + struct hlist_head heads[SWEVENT_HLIST_SIZE]; 723 + struct rcu_head rcu_head; 726 724 }; 727 725 728 726 #define PERF_ATTACH_CONTEXT 0x01 ··· 735 733 * This is a per-cpu dynamically allocated data structure. 736 734 */ 737 735 struct perf_cgroup_info { 738 - u64 time; 739 - u64 timestamp; 736 + u64 time; 737 + u64 timestamp; 740 738 }; 741 739 742 740 struct perf_cgroup { 743 - struct cgroup_subsys_state css; 744 - struct perf_cgroup_info *info; /* timing info, one per cpu */ 741 + struct cgroup_subsys_state css; 742 + struct perf_cgroup_info *info; /* timing info, one per cpu */ 745 743 }; 746 744 #endif 747 745 ··· 925 923 926 924 /* 927 925 * Number of contexts where an event can trigger: 928 - * task, softirq, hardirq, nmi. 926 + * task, softirq, hardirq, nmi. 929 927 */ 930 928 #define PERF_NR_CONTEXTS 4 931 929 ··· 1003 1001 struct perf_raw_record *raw; 1004 1002 }; 1005 1003 1006 - static inline 1007 - void perf_sample_data_init(struct perf_sample_data *data, u64 addr) 1004 + static inline void perf_sample_data_init(struct perf_sample_data *data, u64 addr) 1008 1005 { 1009 1006 data->addr = addr; 1010 1007 data->raw = NULL; ··· 1035 1034 return event->pmu->task_ctx_nr == perf_sw_context; 1036 1035 } 1037 1036 1038 - extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; 1037 + extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; 1039 1038 1040 1039 extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); 1041 1040 1042 1041 #ifndef perf_arch_fetch_caller_regs 1043 - static inline void 1044 - perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip) { } 1042 + static inline void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip) { } 1045 1043 #endif 1046 1044 1047 1045 /* ··· 1063 1063 { 1064 1064 struct pt_regs hot_regs; 1065 1065 1066 - JUMP_LABEL(&perf_swevent_enabled[event_id], have_event); 1067 - return; 1068 - 1069 - have_event: 1070 - if (!regs) { 1071 - perf_fetch_caller_regs(&hot_regs); 1072 - regs = &hot_regs; 1066 + if (static_branch(&perf_swevent_enabled[event_id])) { 1067 + if (!regs) { 1068 + perf_fetch_caller_regs(&hot_regs); 1069 + regs = &hot_regs; 1070 + } 1071 + __perf_sw_event(event_id, nr, nmi, regs, addr); 1073 1072 } 1074 - __perf_sw_event(event_id, nr, nmi, regs, addr); 1075 1073 } 1076 1074 1077 - extern atomic_t perf_sched_events; 1075 + extern struct jump_label_key perf_sched_events; 1078 1076 1079 1077 static inline void perf_event_task_sched_in(struct task_struct *task) 1080 1078 { 1081 - COND_STMT(&perf_sched_events, __perf_event_task_sched_in(task)); 1079 + if (static_branch(&perf_sched_events)) 1080 + __perf_event_task_sched_in(task); 1082 1081 } 1083 1082 1084 - static inline 1085 - void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next) 1083 + static inline void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next) 1086 1084 { 1087 1085 perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); 1088 1086 ··· 1098 1100 /* Callchains */ 1099 1101 DECLARE_PER_CPU(struct perf_callchain_entry, perf_callchain_entry); 1100 1102 1101 - extern void perf_callchain_user(struct perf_callchain_entry *entry, 1102 - struct pt_regs *regs); 1103 - extern void perf_callchain_kernel(struct perf_callchain_entry *entry, 1104 - struct pt_regs *regs); 1103 + extern void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs); 1104 + extern void perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs); 1105 1105 1106 - 1107 - static inline void 1108 - perf_callchain_store(struct perf_callchain_entry *entry, u64 ip) 1106 + static inline void perf_callchain_store(struct perf_callchain_entry *entry, u64 ip) 1109 1107 { 1110 1108 if (entry->nr < PERF_MAX_STACK_DEPTH) 1111 1109 entry->ip[entry->nr++] = ip; ··· 1137 1143 extern void perf_bp_event(struct perf_event *event, void *data); 1138 1144 1139 1145 #ifndef perf_misc_flags 1140 - #define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \ 1141 - PERF_RECORD_MISC_KERNEL) 1142 - #define perf_instruction_pointer(regs) instruction_pointer(regs) 1146 + # define perf_misc_flags(regs) \ 1147 + (user_mode(regs) ? PERF_RECORD_MISC_USER : PERF_RECORD_MISC_KERNEL) 1148 + # define perf_instruction_pointer(regs) instruction_pointer(regs) 1143 1149 #endif 1144 1150 1145 1151 extern int perf_output_begin(struct perf_output_handle *handle, ··· 1174 1180 perf_bp_event(struct perf_event *event, void *data) { } 1175 1181 1176 1182 static inline int perf_register_guest_info_callbacks 1177 - (struct perf_guest_info_callbacks *callbacks) { return 0; } 1183 + (struct perf_guest_info_callbacks *callbacks) { return 0; } 1178 1184 static inline int perf_unregister_guest_info_callbacks 1179 - (struct perf_guest_info_callbacks *callbacks) { return 0; } 1185 + (struct perf_guest_info_callbacks *callbacks) { return 0; } 1180 1186 1181 1187 static inline void perf_event_mmap(struct vm_area_struct *vma) { } 1182 1188 static inline void perf_event_comm(struct task_struct *tsk) { } ··· 1189 1195 static inline void perf_event_task_tick(void) { } 1190 1196 #endif 1191 1197 1192 - #define perf_output_put(handle, x) \ 1193 - perf_output_copy((handle), &(x), sizeof(x)) 1198 + #define perf_output_put(handle, x) perf_output_copy((handle), &(x), sizeof(x)) 1194 1199 1195 1200 /* 1196 1201 * This has to have a higher priority than migration_notifier in sched.c. 1197 1202 */ 1198 - #define perf_cpu_notifier(fn) \ 1199 - do { \ 1200 - static struct notifier_block fn##_nb __cpuinitdata = \ 1201 - { .notifier_call = fn, .priority = CPU_PRI_PERF }; \ 1202 - fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ 1203 - (void *)(unsigned long)smp_processor_id()); \ 1204 - fn(&fn##_nb, (unsigned long)CPU_STARTING, \ 1205 - (void *)(unsigned long)smp_processor_id()); \ 1206 - fn(&fn##_nb, (unsigned long)CPU_ONLINE, \ 1207 - (void *)(unsigned long)smp_processor_id()); \ 1208 - register_cpu_notifier(&fn##_nb); \ 1203 + #define perf_cpu_notifier(fn) \ 1204 + do { \ 1205 + static struct notifier_block fn##_nb __cpuinitdata = \ 1206 + { .notifier_call = fn, .priority = CPU_PRI_PERF }; \ 1207 + fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ 1208 + (void *)(unsigned long)smp_processor_id()); \ 1209 + fn(&fn##_nb, (unsigned long)CPU_STARTING, \ 1210 + (void *)(unsigned long)smp_processor_id()); \ 1211 + fn(&fn##_nb, (unsigned long)CPU_ONLINE, \ 1212 + (void *)(unsigned long)smp_processor_id()); \ 1213 + register_cpu_notifier(&fn##_nb); \ 1209 1214 } while (0) 1210 1215 1211 1216 #endif /* __KERNEL__ */
+10 -12
include/linux/tracepoint.h
··· 29 29 30 30 struct tracepoint { 31 31 const char *name; /* Tracepoint name */ 32 - int state; /* State. */ 32 + struct jump_label_key key; 33 33 void (*regfunc)(void); 34 34 void (*unregfunc)(void); 35 35 struct tracepoint_func __rcu *funcs; ··· 146 146 extern struct tracepoint __tracepoint_##name; \ 147 147 static inline void trace_##name(proto) \ 148 148 { \ 149 - JUMP_LABEL(&__tracepoint_##name.state, do_trace); \ 150 - return; \ 151 - do_trace: \ 149 + if (static_branch(&__tracepoint_##name.key)) \ 152 150 __DO_TRACE(&__tracepoint_##name, \ 153 151 TP_PROTO(data_proto), \ 154 152 TP_ARGS(data_args), \ ··· 174 176 * structures, so we create an array of pointers that will be used for iteration 175 177 * on the tracepoints. 176 178 */ 177 - #define DEFINE_TRACE_FN(name, reg, unreg) \ 178 - static const char __tpstrtab_##name[] \ 179 - __attribute__((section("__tracepoints_strings"))) = #name; \ 180 - struct tracepoint __tracepoint_##name \ 181 - __attribute__((section("__tracepoints"))) = \ 182 - { __tpstrtab_##name, 0, reg, unreg, NULL }; \ 183 - static struct tracepoint * const __tracepoint_ptr_##name __used \ 184 - __attribute__((section("__tracepoints_ptrs"))) = \ 179 + #define DEFINE_TRACE_FN(name, reg, unreg) \ 180 + static const char __tpstrtab_##name[] \ 181 + __attribute__((section("__tracepoints_strings"))) = #name; \ 182 + struct tracepoint __tracepoint_##name \ 183 + __attribute__((section("__tracepoints"))) = \ 184 + { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\ 185 + static struct tracepoint * const __tracepoint_ptr_##name __used \ 186 + __attribute__((section("__tracepoints_ptrs"))) = \ 185 187 &__tracepoint_##name; 186 188 187 189 #define DEFINE_TRACE(name) \
+3 -3
kernel/Makefile
··· 21 21 CFLAGS_REMOVE_rtmutex-debug.o = -pg 22 22 CFLAGS_REMOVE_cgroup-debug.o = -pg 23 23 CFLAGS_REMOVE_sched_clock.o = -pg 24 - CFLAGS_REMOVE_perf_event.o = -pg 25 24 CFLAGS_REMOVE_irq_work.o = -pg 26 25 endif 27 26 ··· 102 103 obj-$(CONFIG_TRACEPOINTS) += trace/ 103 104 obj-$(CONFIG_SMP) += sched_cpupri.o 104 105 obj-$(CONFIG_IRQ_WORK) += irq_work.o 105 - obj-$(CONFIG_PERF_EVENTS) += perf_event.o 106 - obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o 106 + 107 + obj-$(CONFIG_PERF_EVENTS) += events/ 108 + 107 109 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o 108 110 obj-$(CONFIG_PADATA) += padata.o 109 111 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+6
kernel/events/Makefile
··· 1 + ifdef CONFIG_FUNCTION_TRACER 2 + CFLAGS_REMOVE_core.o = -pg 3 + endif 4 + 5 + obj-y := core.o 6 + obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
+8
kernel/extable.c
··· 72 72 return 0; 73 73 } 74 74 75 + int core_kernel_data(unsigned long addr) 76 + { 77 + if (addr >= (unsigned long)_sdata && 78 + addr < (unsigned long)_edata) 79 + return 1; 80 + return 0; 81 + } 82 + 75 83 int __kernel_text_address(unsigned long addr) 76 84 { 77 85 if (core_kernel_text(addr))
kernel/hw_breakpoint.c kernel/events/hw_breakpoint.c
+280 -383
kernel/jump_label.c
··· 2 2 * jump label support 3 3 * 4 4 * Copyright (C) 2009 Jason Baron <jbaron@redhat.com> 5 + * Copyright (C) 2011 Peter Zijlstra <pzijlstr@redhat.com> 5 6 * 6 7 */ 7 - #include <linux/jump_label.h> 8 8 #include <linux/memory.h> 9 9 #include <linux/uaccess.h> 10 10 #include <linux/module.h> 11 11 #include <linux/list.h> 12 - #include <linux/jhash.h> 13 12 #include <linux/slab.h> 14 13 #include <linux/sort.h> 15 14 #include <linux/err.h> 15 + #include <linux/jump_label.h> 16 16 17 17 #ifdef HAVE_JUMP_LABEL 18 18 19 - #define JUMP_LABEL_HASH_BITS 6 20 - #define JUMP_LABEL_TABLE_SIZE (1 << JUMP_LABEL_HASH_BITS) 21 - static struct hlist_head jump_label_table[JUMP_LABEL_TABLE_SIZE]; 22 - 23 19 /* mutex to protect coming/going of the the jump_label table */ 24 20 static DEFINE_MUTEX(jump_label_mutex); 25 - 26 - struct jump_label_entry { 27 - struct hlist_node hlist; 28 - struct jump_entry *table; 29 - int nr_entries; 30 - /* hang modules off here */ 31 - struct hlist_head modules; 32 - unsigned long key; 33 - }; 34 - 35 - struct jump_label_module_entry { 36 - struct hlist_node hlist; 37 - struct jump_entry *table; 38 - int nr_entries; 39 - struct module *mod; 40 - }; 41 21 42 22 void jump_label_lock(void) 43 23 { ··· 27 47 void jump_label_unlock(void) 28 48 { 29 49 mutex_unlock(&jump_label_mutex); 50 + } 51 + 52 + bool jump_label_enabled(struct jump_label_key *key) 53 + { 54 + return !!atomic_read(&key->enabled); 30 55 } 31 56 32 57 static int jump_label_cmp(const void *a, const void *b) ··· 49 64 } 50 65 51 66 static void 52 - sort_jump_label_entries(struct jump_entry *start, struct jump_entry *stop) 67 + jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop) 53 68 { 54 69 unsigned long size; 55 70 ··· 58 73 sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL); 59 74 } 60 75 61 - static struct jump_label_entry *get_jump_label_entry(jump_label_t key) 76 + static void jump_label_update(struct jump_label_key *key, int enable); 77 + 78 + void jump_label_inc(struct jump_label_key *key) 62 79 { 63 - struct hlist_head *head; 64 - struct hlist_node *node; 65 - struct jump_label_entry *e; 66 - u32 hash = jhash((void *)&key, sizeof(jump_label_t), 0); 67 - 68 - head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)]; 69 - hlist_for_each_entry(e, node, head, hlist) { 70 - if (key == e->key) 71 - return e; 72 - } 73 - return NULL; 74 - } 75 - 76 - static struct jump_label_entry * 77 - add_jump_label_entry(jump_label_t key, int nr_entries, struct jump_entry *table) 78 - { 79 - struct hlist_head *head; 80 - struct jump_label_entry *e; 81 - u32 hash; 82 - 83 - e = get_jump_label_entry(key); 84 - if (e) 85 - return ERR_PTR(-EEXIST); 86 - 87 - e = kmalloc(sizeof(struct jump_label_entry), GFP_KERNEL); 88 - if (!e) 89 - return ERR_PTR(-ENOMEM); 90 - 91 - hash = jhash((void *)&key, sizeof(jump_label_t), 0); 92 - head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)]; 93 - e->key = key; 94 - e->table = table; 95 - e->nr_entries = nr_entries; 96 - INIT_HLIST_HEAD(&(e->modules)); 97 - hlist_add_head(&e->hlist, head); 98 - return e; 99 - } 100 - 101 - static int 102 - build_jump_label_hashtable(struct jump_entry *start, struct jump_entry *stop) 103 - { 104 - struct jump_entry *iter, *iter_begin; 105 - struct jump_label_entry *entry; 106 - int count; 107 - 108 - sort_jump_label_entries(start, stop); 109 - iter = start; 110 - while (iter < stop) { 111 - entry = get_jump_label_entry(iter->key); 112 - if (!entry) { 113 - iter_begin = iter; 114 - count = 0; 115 - while ((iter < stop) && 116 - (iter->key == iter_begin->key)) { 117 - iter++; 118 - count++; 119 - } 120 - entry = add_jump_label_entry(iter_begin->key, 121 - count, iter_begin); 122 - if (IS_ERR(entry)) 123 - return PTR_ERR(entry); 124 - } else { 125 - WARN_ONCE(1, KERN_ERR "build_jump_hashtable: unexpected entry!\n"); 126 - return -1; 127 - } 128 - } 129 - return 0; 130 - } 131 - 132 - /*** 133 - * jump_label_update - update jump label text 134 - * @key - key value associated with a a jump label 135 - * @type - enum set to JUMP_LABEL_ENABLE or JUMP_LABEL_DISABLE 136 - * 137 - * Will enable/disable the jump for jump label @key, depending on the 138 - * value of @type. 139 - * 140 - */ 141 - 142 - void jump_label_update(unsigned long key, enum jump_label_type type) 143 - { 144 - struct jump_entry *iter; 145 - struct jump_label_entry *entry; 146 - struct hlist_node *module_node; 147 - struct jump_label_module_entry *e_module; 148 - int count; 80 + if (atomic_inc_not_zero(&key->enabled)) 81 + return; 149 82 150 83 jump_label_lock(); 151 - entry = get_jump_label_entry((jump_label_t)key); 152 - if (entry) { 153 - count = entry->nr_entries; 154 - iter = entry->table; 155 - while (count--) { 156 - if (kernel_text_address(iter->code)) 157 - arch_jump_label_transform(iter, type); 158 - iter++; 159 - } 160 - /* eanble/disable jump labels in modules */ 161 - hlist_for_each_entry(e_module, module_node, &(entry->modules), 162 - hlist) { 163 - count = e_module->nr_entries; 164 - iter = e_module->table; 165 - while (count--) { 166 - if (iter->key && 167 - kernel_text_address(iter->code)) 168 - arch_jump_label_transform(iter, type); 169 - iter++; 170 - } 171 - } 172 - } 84 + if (atomic_add_return(1, &key->enabled) == 1) 85 + jump_label_update(key, JUMP_LABEL_ENABLE); 86 + jump_label_unlock(); 87 + } 88 + 89 + void jump_label_dec(struct jump_label_key *key) 90 + { 91 + if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) 92 + return; 93 + 94 + jump_label_update(key, JUMP_LABEL_DISABLE); 173 95 jump_label_unlock(); 174 96 } 175 97 ··· 89 197 return 0; 90 198 } 91 199 92 - #ifdef CONFIG_MODULES 93 - 94 - static int module_conflict(void *start, void *end) 200 + static int __jump_label_text_reserved(struct jump_entry *iter_start, 201 + struct jump_entry *iter_stop, void *start, void *end) 95 202 { 96 - struct hlist_head *head; 97 - struct hlist_node *node, *node_next, *module_node, *module_node_next; 98 - struct jump_label_entry *e; 99 - struct jump_label_module_entry *e_module; 100 203 struct jump_entry *iter; 101 - int i, count; 102 - int conflict = 0; 103 204 104 - for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) { 105 - head = &jump_label_table[i]; 106 - hlist_for_each_entry_safe(e, node, node_next, head, hlist) { 107 - hlist_for_each_entry_safe(e_module, module_node, 108 - module_node_next, 109 - &(e->modules), hlist) { 110 - count = e_module->nr_entries; 111 - iter = e_module->table; 112 - while (count--) { 113 - if (addr_conflict(iter, start, end)) { 114 - conflict = 1; 115 - goto out; 116 - } 117 - iter++; 118 - } 119 - } 120 - } 205 + iter = iter_start; 206 + while (iter < iter_stop) { 207 + if (addr_conflict(iter, start, end)) 208 + return 1; 209 + iter++; 121 210 } 122 - out: 123 - return conflict; 211 + 212 + return 0; 124 213 } 125 214 215 + static void __jump_label_update(struct jump_label_key *key, 216 + struct jump_entry *entry, int enable) 217 + { 218 + for (; entry->key == (jump_label_t)(unsigned long)key; entry++) { 219 + /* 220 + * entry->code set to 0 invalidates module init text sections 221 + * kernel_text_address() verifies we are not in core kernel 222 + * init code, see jump_label_invalidate_module_init(). 223 + */ 224 + if (entry->code && kernel_text_address(entry->code)) 225 + arch_jump_label_transform(entry, enable); 226 + } 227 + } 228 + 229 + /* 230 + * Not all archs need this. 231 + */ 232 + void __weak arch_jump_label_text_poke_early(jump_label_t addr) 233 + { 234 + } 235 + 236 + static __init int jump_label_init(void) 237 + { 238 + struct jump_entry *iter_start = __start___jump_table; 239 + struct jump_entry *iter_stop = __stop___jump_table; 240 + struct jump_label_key *key = NULL; 241 + struct jump_entry *iter; 242 + 243 + jump_label_lock(); 244 + jump_label_sort_entries(iter_start, iter_stop); 245 + 246 + for (iter = iter_start; iter < iter_stop; iter++) { 247 + arch_jump_label_text_poke_early(iter->code); 248 + if (iter->key == (jump_label_t)(unsigned long)key) 249 + continue; 250 + 251 + key = (struct jump_label_key *)(unsigned long)iter->key; 252 + atomic_set(&key->enabled, 0); 253 + key->entries = iter; 254 + #ifdef CONFIG_MODULES 255 + key->next = NULL; 126 256 #endif 257 + } 258 + jump_label_unlock(); 259 + 260 + return 0; 261 + } 262 + early_initcall(jump_label_init); 263 + 264 + #ifdef CONFIG_MODULES 265 + 266 + struct jump_label_mod { 267 + struct jump_label_mod *next; 268 + struct jump_entry *entries; 269 + struct module *mod; 270 + }; 271 + 272 + static int __jump_label_mod_text_reserved(void *start, void *end) 273 + { 274 + struct module *mod; 275 + 276 + mod = __module_text_address((unsigned long)start); 277 + if (!mod) 278 + return 0; 279 + 280 + WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod); 281 + 282 + return __jump_label_text_reserved(mod->jump_entries, 283 + mod->jump_entries + mod->num_jump_entries, 284 + start, end); 285 + } 286 + 287 + static void __jump_label_mod_update(struct jump_label_key *key, int enable) 288 + { 289 + struct jump_label_mod *mod = key->next; 290 + 291 + while (mod) { 292 + __jump_label_update(key, mod->entries, enable); 293 + mod = mod->next; 294 + } 295 + } 296 + 297 + /*** 298 + * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop() 299 + * @mod: module to patch 300 + * 301 + * Allow for run-time selection of the optimal nops. Before the module 302 + * loads patch these with arch_get_jump_label_nop(), which is specified by 303 + * the arch specific jump label code. 304 + */ 305 + void jump_label_apply_nops(struct module *mod) 306 + { 307 + struct jump_entry *iter_start = mod->jump_entries; 308 + struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; 309 + struct jump_entry *iter; 310 + 311 + /* if the module doesn't have jump label entries, just return */ 312 + if (iter_start == iter_stop) 313 + return; 314 + 315 + for (iter = iter_start; iter < iter_stop; iter++) 316 + arch_jump_label_text_poke_early(iter->code); 317 + } 318 + 319 + static int jump_label_add_module(struct module *mod) 320 + { 321 + struct jump_entry *iter_start = mod->jump_entries; 322 + struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; 323 + struct jump_entry *iter; 324 + struct jump_label_key *key = NULL; 325 + struct jump_label_mod *jlm; 326 + 327 + /* if the module doesn't have jump label entries, just return */ 328 + if (iter_start == iter_stop) 329 + return 0; 330 + 331 + jump_label_sort_entries(iter_start, iter_stop); 332 + 333 + for (iter = iter_start; iter < iter_stop; iter++) { 334 + if (iter->key == (jump_label_t)(unsigned long)key) 335 + continue; 336 + 337 + key = (struct jump_label_key *)(unsigned long)iter->key; 338 + 339 + if (__module_address(iter->key) == mod) { 340 + atomic_set(&key->enabled, 0); 341 + key->entries = iter; 342 + key->next = NULL; 343 + continue; 344 + } 345 + 346 + jlm = kzalloc(sizeof(struct jump_label_mod), GFP_KERNEL); 347 + if (!jlm) 348 + return -ENOMEM; 349 + 350 + jlm->mod = mod; 351 + jlm->entries = iter; 352 + jlm->next = key->next; 353 + key->next = jlm; 354 + 355 + if (jump_label_enabled(key)) 356 + __jump_label_update(key, iter, JUMP_LABEL_ENABLE); 357 + } 358 + 359 + return 0; 360 + } 361 + 362 + static void jump_label_del_module(struct module *mod) 363 + { 364 + struct jump_entry *iter_start = mod->jump_entries; 365 + struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; 366 + struct jump_entry *iter; 367 + struct jump_label_key *key = NULL; 368 + struct jump_label_mod *jlm, **prev; 369 + 370 + for (iter = iter_start; iter < iter_stop; iter++) { 371 + if (iter->key == (jump_label_t)(unsigned long)key) 372 + continue; 373 + 374 + key = (struct jump_label_key *)(unsigned long)iter->key; 375 + 376 + if (__module_address(iter->key) == mod) 377 + continue; 378 + 379 + prev = &key->next; 380 + jlm = key->next; 381 + 382 + while (jlm && jlm->mod != mod) { 383 + prev = &jlm->next; 384 + jlm = jlm->next; 385 + } 386 + 387 + if (jlm) { 388 + *prev = jlm->next; 389 + kfree(jlm); 390 + } 391 + } 392 + } 393 + 394 + static void jump_label_invalidate_module_init(struct module *mod) 395 + { 396 + struct jump_entry *iter_start = mod->jump_entries; 397 + struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; 398 + struct jump_entry *iter; 399 + 400 + for (iter = iter_start; iter < iter_stop; iter++) { 401 + if (within_module_init(iter->code, mod)) 402 + iter->code = 0; 403 + } 404 + } 405 + 406 + static int 407 + jump_label_module_notify(struct notifier_block *self, unsigned long val, 408 + void *data) 409 + { 410 + struct module *mod = data; 411 + int ret = 0; 412 + 413 + switch (val) { 414 + case MODULE_STATE_COMING: 415 + jump_label_lock(); 416 + ret = jump_label_add_module(mod); 417 + if (ret) 418 + jump_label_del_module(mod); 419 + jump_label_unlock(); 420 + break; 421 + case MODULE_STATE_GOING: 422 + jump_label_lock(); 423 + jump_label_del_module(mod); 424 + jump_label_unlock(); 425 + break; 426 + case MODULE_STATE_LIVE: 427 + jump_label_lock(); 428 + jump_label_invalidate_module_init(mod); 429 + jump_label_unlock(); 430 + break; 431 + } 432 + 433 + return notifier_from_errno(ret); 434 + } 435 + 436 + struct notifier_block jump_label_module_nb = { 437 + .notifier_call = jump_label_module_notify, 438 + .priority = 1, /* higher than tracepoints */ 439 + }; 440 + 441 + static __init int jump_label_init_module(void) 442 + { 443 + return register_module_notifier(&jump_label_module_nb); 444 + } 445 + early_initcall(jump_label_init_module); 446 + 447 + #endif /* CONFIG_MODULES */ 127 448 128 449 /*** 129 450 * jump_label_text_reserved - check if addr range is reserved ··· 353 248 */ 354 249 int jump_label_text_reserved(void *start, void *end) 355 250 { 356 - struct jump_entry *iter; 357 - struct jump_entry *iter_start = __start___jump_table; 358 - struct jump_entry *iter_stop = __start___jump_table; 359 - int conflict = 0; 251 + int ret = __jump_label_text_reserved(__start___jump_table, 252 + __stop___jump_table, start, end); 360 253 361 - iter = iter_start; 362 - while (iter < iter_stop) { 363 - if (addr_conflict(iter, start, end)) { 364 - conflict = 1; 365 - goto out; 366 - } 367 - iter++; 368 - } 254 + if (ret) 255 + return ret; 369 256 370 - /* now check modules */ 371 257 #ifdef CONFIG_MODULES 372 - conflict = module_conflict(start, end); 258 + ret = __jump_label_mod_text_reserved(start, end); 373 259 #endif 374 - out: 375 - return conflict; 376 - } 377 - 378 - /* 379 - * Not all archs need this. 380 - */ 381 - void __weak arch_jump_label_text_poke_early(jump_label_t addr) 382 - { 383 - } 384 - 385 - static __init int init_jump_label(void) 386 - { 387 - int ret; 388 - struct jump_entry *iter_start = __start___jump_table; 389 - struct jump_entry *iter_stop = __stop___jump_table; 390 - struct jump_entry *iter; 391 - 392 - jump_label_lock(); 393 - ret = build_jump_label_hashtable(__start___jump_table, 394 - __stop___jump_table); 395 - iter = iter_start; 396 - while (iter < iter_stop) { 397 - arch_jump_label_text_poke_early(iter->code); 398 - iter++; 399 - } 400 - jump_label_unlock(); 401 260 return ret; 402 261 } 403 - early_initcall(init_jump_label); 262 + 263 + static void jump_label_update(struct jump_label_key *key, int enable) 264 + { 265 + struct jump_entry *entry = key->entries; 266 + 267 + /* if there are no users, entry can be NULL */ 268 + if (entry) 269 + __jump_label_update(key, entry, enable); 404 270 405 271 #ifdef CONFIG_MODULES 406 - 407 - static struct jump_label_module_entry * 408 - add_jump_label_module_entry(struct jump_label_entry *entry, 409 - struct jump_entry *iter_begin, 410 - int count, struct module *mod) 411 - { 412 - struct jump_label_module_entry *e; 413 - 414 - e = kmalloc(sizeof(struct jump_label_module_entry), GFP_KERNEL); 415 - if (!e) 416 - return ERR_PTR(-ENOMEM); 417 - e->mod = mod; 418 - e->nr_entries = count; 419 - e->table = iter_begin; 420 - hlist_add_head(&e->hlist, &entry->modules); 421 - return e; 272 + __jump_label_mod_update(key, enable); 273 + #endif 422 274 } 423 - 424 - static int add_jump_label_module(struct module *mod) 425 - { 426 - struct jump_entry *iter, *iter_begin; 427 - struct jump_label_entry *entry; 428 - struct jump_label_module_entry *module_entry; 429 - int count; 430 - 431 - /* if the module doesn't have jump label entries, just return */ 432 - if (!mod->num_jump_entries) 433 - return 0; 434 - 435 - sort_jump_label_entries(mod->jump_entries, 436 - mod->jump_entries + mod->num_jump_entries); 437 - iter = mod->jump_entries; 438 - while (iter < mod->jump_entries + mod->num_jump_entries) { 439 - entry = get_jump_label_entry(iter->key); 440 - iter_begin = iter; 441 - count = 0; 442 - while ((iter < mod->jump_entries + mod->num_jump_entries) && 443 - (iter->key == iter_begin->key)) { 444 - iter++; 445 - count++; 446 - } 447 - if (!entry) { 448 - entry = add_jump_label_entry(iter_begin->key, 0, NULL); 449 - if (IS_ERR(entry)) 450 - return PTR_ERR(entry); 451 - } 452 - module_entry = add_jump_label_module_entry(entry, iter_begin, 453 - count, mod); 454 - if (IS_ERR(module_entry)) 455 - return PTR_ERR(module_entry); 456 - } 457 - return 0; 458 - } 459 - 460 - static void remove_jump_label_module(struct module *mod) 461 - { 462 - struct hlist_head *head; 463 - struct hlist_node *node, *node_next, *module_node, *module_node_next; 464 - struct jump_label_entry *e; 465 - struct jump_label_module_entry *e_module; 466 - int i; 467 - 468 - /* if the module doesn't have jump label entries, just return */ 469 - if (!mod->num_jump_entries) 470 - return; 471 - 472 - for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) { 473 - head = &jump_label_table[i]; 474 - hlist_for_each_entry_safe(e, node, node_next, head, hlist) { 475 - hlist_for_each_entry_safe(e_module, module_node, 476 - module_node_next, 477 - &(e->modules), hlist) { 478 - if (e_module->mod == mod) { 479 - hlist_del(&e_module->hlist); 480 - kfree(e_module); 481 - } 482 - } 483 - if (hlist_empty(&e->modules) && (e->nr_entries == 0)) { 484 - hlist_del(&e->hlist); 485 - kfree(e); 486 - } 487 - } 488 - } 489 - } 490 - 491 - static void remove_jump_label_module_init(struct module *mod) 492 - { 493 - struct hlist_head *head; 494 - struct hlist_node *node, *node_next, *module_node, *module_node_next; 495 - struct jump_label_entry *e; 496 - struct jump_label_module_entry *e_module; 497 - struct jump_entry *iter; 498 - int i, count; 499 - 500 - /* if the module doesn't have jump label entries, just return */ 501 - if (!mod->num_jump_entries) 502 - return; 503 - 504 - for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) { 505 - head = &jump_label_table[i]; 506 - hlist_for_each_entry_safe(e, node, node_next, head, hlist) { 507 - hlist_for_each_entry_safe(e_module, module_node, 508 - module_node_next, 509 - &(e->modules), hlist) { 510 - if (e_module->mod != mod) 511 - continue; 512 - count = e_module->nr_entries; 513 - iter = e_module->table; 514 - while (count--) { 515 - if (within_module_init(iter->code, mod)) 516 - iter->key = 0; 517 - iter++; 518 - } 519 - } 520 - } 521 - } 522 - } 523 - 524 - static int 525 - jump_label_module_notify(struct notifier_block *self, unsigned long val, 526 - void *data) 527 - { 528 - struct module *mod = data; 529 - int ret = 0; 530 - 531 - switch (val) { 532 - case MODULE_STATE_COMING: 533 - jump_label_lock(); 534 - ret = add_jump_label_module(mod); 535 - if (ret) 536 - remove_jump_label_module(mod); 537 - jump_label_unlock(); 538 - break; 539 - case MODULE_STATE_GOING: 540 - jump_label_lock(); 541 - remove_jump_label_module(mod); 542 - jump_label_unlock(); 543 - break; 544 - case MODULE_STATE_LIVE: 545 - jump_label_lock(); 546 - remove_jump_label_module_init(mod); 547 - jump_label_unlock(); 548 - break; 549 - } 550 - return ret; 551 - } 552 - 553 - /*** 554 - * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop() 555 - * @mod: module to patch 556 - * 557 - * Allow for run-time selection of the optimal nops. Before the module 558 - * loads patch these with arch_get_jump_label_nop(), which is specified by 559 - * the arch specific jump label code. 560 - */ 561 - void jump_label_apply_nops(struct module *mod) 562 - { 563 - struct jump_entry *iter; 564 - 565 - /* if the module doesn't have jump label entries, just return */ 566 - if (!mod->num_jump_entries) 567 - return; 568 - 569 - iter = mod->jump_entries; 570 - while (iter < mod->jump_entries + mod->num_jump_entries) { 571 - arch_jump_label_text_poke_early(iter->code); 572 - iter++; 573 - } 574 - } 575 - 576 - struct notifier_block jump_label_module_nb = { 577 - .notifier_call = jump_label_module_notify, 578 - .priority = 0, 579 - }; 580 - 581 - static __init int init_jump_label_module(void) 582 - { 583 - return register_module_notifier(&jump_label_module_nb); 584 - } 585 - early_initcall(init_jump_label_module); 586 - 587 - #endif /* CONFIG_MODULES */ 588 275 589 276 #endif
+22 -22
kernel/perf_event.c kernel/events/core.c
··· 2 2 * Performance events core code: 3 3 * 4 4 * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> 5 - * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar 6 - * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> 5 + * Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar 6 + * Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> 7 7 * Copyright � 2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 8 8 * 9 9 * For licensing details see kernel-base/COPYING ··· 39 39 #include <asm/irq_regs.h> 40 40 41 41 struct remote_function_call { 42 - struct task_struct *p; 43 - int (*func)(void *info); 44 - void *info; 45 - int ret; 42 + struct task_struct *p; 43 + int (*func)(void *info); 44 + void *info; 45 + int ret; 46 46 }; 47 47 48 48 static void remote_function(void *data) ··· 76 76 task_function_call(struct task_struct *p, int (*func) (void *info), void *info) 77 77 { 78 78 struct remote_function_call data = { 79 - .p = p, 80 - .func = func, 81 - .info = info, 82 - .ret = -ESRCH, /* No such (running) process */ 79 + .p = p, 80 + .func = func, 81 + .info = info, 82 + .ret = -ESRCH, /* No such (running) process */ 83 83 }; 84 84 85 85 if (task_curr(p)) ··· 100 100 static int cpu_function_call(int cpu, int (*func) (void *info), void *info) 101 101 { 102 102 struct remote_function_call data = { 103 - .p = NULL, 104 - .func = func, 105 - .info = info, 106 - .ret = -ENXIO, /* No such CPU */ 103 + .p = NULL, 104 + .func = func, 105 + .info = info, 106 + .ret = -ENXIO, /* No such CPU */ 107 107 }; 108 108 109 109 smp_call_function_single(cpu, remote_function, &data, 1); ··· 125 125 * perf_sched_events : >0 events exist 126 126 * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu 127 127 */ 128 - atomic_t perf_sched_events __read_mostly; 128 + struct jump_label_key perf_sched_events __read_mostly; 129 129 static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); 130 130 131 131 static atomic_t nr_mmap_events __read_mostly; ··· 5429 5429 return err; 5430 5430 } 5431 5431 5432 - atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; 5432 + struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; 5433 5433 5434 5434 static void sw_perf_event_destroy(struct perf_event *event) 5435 5435 { ··· 7445 7445 } 7446 7446 7447 7447 struct cgroup_subsys perf_subsys = { 7448 - .name = "perf_event", 7449 - .subsys_id = perf_subsys_id, 7450 - .create = perf_cgroup_create, 7451 - .destroy = perf_cgroup_destroy, 7452 - .exit = perf_cgroup_exit, 7453 - .attach = perf_cgroup_attach, 7448 + .name = "perf_event", 7449 + .subsys_id = perf_subsys_id, 7450 + .create = perf_cgroup_create, 7451 + .destroy = perf_cgroup_destroy, 7452 + .exit = perf_cgroup_exit, 7453 + .attach = perf_cgroup_attach, 7454 7454 }; 7455 7455 #endif /* CONFIG_CGROUP_PERF */
+969 -316
kernel/trace/ftrace.c
··· 39 39 #include "trace_stat.h" 40 40 41 41 #define FTRACE_WARN_ON(cond) \ 42 - do { \ 43 - if (WARN_ON(cond)) \ 42 + ({ \ 43 + int ___r = cond; \ 44 + if (WARN_ON(___r)) \ 44 45 ftrace_kill(); \ 45 - } while (0) 46 + ___r; \ 47 + }) 46 48 47 49 #define FTRACE_WARN_ON_ONCE(cond) \ 48 - do { \ 49 - if (WARN_ON_ONCE(cond)) \ 50 + ({ \ 51 + int ___r = cond; \ 52 + if (WARN_ON_ONCE(___r)) \ 50 53 ftrace_kill(); \ 51 - } while (0) 54 + ___r; \ 55 + }) 52 56 53 57 /* hash bits for specific function selection */ 54 58 #define FTRACE_HASH_BITS 7 55 59 #define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS) 60 + #define FTRACE_HASH_DEFAULT_BITS 10 61 + #define FTRACE_HASH_MAX_BITS 12 56 62 57 63 /* ftrace_enabled is a method to turn ftrace on or off */ 58 64 int ftrace_enabled __read_mostly; ··· 87 81 .func = ftrace_stub, 88 82 }; 89 83 90 - static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end; 84 + static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end; 85 + static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; 91 86 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; 92 87 ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub; 93 88 ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; 89 + static struct ftrace_ops global_ops; 90 + 91 + static void 92 + ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip); 94 93 95 94 /* 96 - * Traverse the ftrace_list, invoking all entries. The reason that we 95 + * Traverse the ftrace_global_list, invoking all entries. The reason that we 97 96 * can use rcu_dereference_raw() is that elements removed from this list 98 97 * are simply leaked, so there is no need to interact with a grace-period 99 98 * mechanism. The rcu_dereference_raw() calls are needed to handle 100 - * concurrent insertions into the ftrace_list. 99 + * concurrent insertions into the ftrace_global_list. 101 100 * 102 101 * Silly Alpha and silly pointer-speculation compiler optimizations! 103 102 */ 104 - static void ftrace_list_func(unsigned long ip, unsigned long parent_ip) 103 + static void ftrace_global_list_func(unsigned long ip, 104 + unsigned long parent_ip) 105 105 { 106 - struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/ 106 + struct ftrace_ops *op = rcu_dereference_raw(ftrace_global_list); /*see above*/ 107 107 108 108 while (op != &ftrace_list_end) { 109 109 op->func(ip, parent_ip); ··· 159 147 } 160 148 #endif 161 149 162 - static int __register_ftrace_function(struct ftrace_ops *ops) 150 + static void update_global_ops(void) 163 151 { 164 - ops->next = ftrace_list; 152 + ftrace_func_t func; 153 + 165 154 /* 166 - * We are entering ops into the ftrace_list but another 167 - * CPU might be walking that list. We need to make sure 168 - * the ops->next pointer is valid before another CPU sees 169 - * the ops pointer included into the ftrace_list. 155 + * If there's only one function registered, then call that 156 + * function directly. Otherwise, we need to iterate over the 157 + * registered callers. 170 158 */ 171 - rcu_assign_pointer(ftrace_list, ops); 159 + if (ftrace_global_list == &ftrace_list_end || 160 + ftrace_global_list->next == &ftrace_list_end) 161 + func = ftrace_global_list->func; 162 + else 163 + func = ftrace_global_list_func; 172 164 173 - if (ftrace_enabled) { 174 - ftrace_func_t func; 175 - 176 - if (ops->next == &ftrace_list_end) 177 - func = ops->func; 178 - else 179 - func = ftrace_list_func; 180 - 181 - if (!list_empty(&ftrace_pids)) { 182 - set_ftrace_pid_function(func); 183 - func = ftrace_pid_func; 184 - } 185 - 186 - /* 187 - * For one func, simply call it directly. 188 - * For more than one func, call the chain. 189 - */ 190 - #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 191 - ftrace_trace_function = func; 192 - #else 193 - __ftrace_trace_function = func; 194 - ftrace_trace_function = ftrace_test_stop_func; 195 - #endif 165 + /* If we filter on pids, update to use the pid function */ 166 + if (!list_empty(&ftrace_pids)) { 167 + set_ftrace_pid_function(func); 168 + func = ftrace_pid_func; 196 169 } 197 170 198 - return 0; 171 + global_ops.func = func; 199 172 } 200 173 201 - static int __unregister_ftrace_function(struct ftrace_ops *ops) 174 + static void update_ftrace_function(void) 175 + { 176 + ftrace_func_t func; 177 + 178 + update_global_ops(); 179 + 180 + /* 181 + * If we are at the end of the list and this ops is 182 + * not dynamic, then have the mcount trampoline call 183 + * the function directly 184 + */ 185 + if (ftrace_ops_list == &ftrace_list_end || 186 + (ftrace_ops_list->next == &ftrace_list_end && 187 + !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC))) 188 + func = ftrace_ops_list->func; 189 + else 190 + func = ftrace_ops_list_func; 191 + 192 + #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 193 + ftrace_trace_function = func; 194 + #else 195 + __ftrace_trace_function = func; 196 + ftrace_trace_function = ftrace_test_stop_func; 197 + #endif 198 + } 199 + 200 + static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) 201 + { 202 + ops->next = *list; 203 + /* 204 + * We are entering ops into the list but another 205 + * CPU might be walking that list. We need to make sure 206 + * the ops->next pointer is valid before another CPU sees 207 + * the ops pointer included into the list. 208 + */ 209 + rcu_assign_pointer(*list, ops); 210 + } 211 + 212 + static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) 202 213 { 203 214 struct ftrace_ops **p; 204 215 ··· 229 194 * If we are removing the last function, then simply point 230 195 * to the ftrace_stub. 231 196 */ 232 - if (ftrace_list == ops && ops->next == &ftrace_list_end) { 233 - ftrace_trace_function = ftrace_stub; 234 - ftrace_list = &ftrace_list_end; 197 + if (*list == ops && ops->next == &ftrace_list_end) { 198 + *list = &ftrace_list_end; 235 199 return 0; 236 200 } 237 201 238 - for (p = &ftrace_list; *p != &ftrace_list_end; p = &(*p)->next) 202 + for (p = list; *p != &ftrace_list_end; p = &(*p)->next) 239 203 if (*p == ops) 240 204 break; 241 205 ··· 242 208 return -1; 243 209 244 210 *p = (*p)->next; 211 + return 0; 212 + } 245 213 246 - if (ftrace_enabled) { 247 - /* If we only have one func left, then call that directly */ 248 - if (ftrace_list->next == &ftrace_list_end) { 249 - ftrace_func_t func = ftrace_list->func; 214 + static int __register_ftrace_function(struct ftrace_ops *ops) 215 + { 216 + if (ftrace_disabled) 217 + return -ENODEV; 250 218 251 - if (!list_empty(&ftrace_pids)) { 252 - set_ftrace_pid_function(func); 253 - func = ftrace_pid_func; 254 - } 255 - #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 256 - ftrace_trace_function = func; 257 - #else 258 - __ftrace_trace_function = func; 259 - #endif 260 - } 261 - } 219 + if (FTRACE_WARN_ON(ops == &global_ops)) 220 + return -EINVAL; 221 + 222 + if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED)) 223 + return -EBUSY; 224 + 225 + if (!core_kernel_data((unsigned long)ops)) 226 + ops->flags |= FTRACE_OPS_FL_DYNAMIC; 227 + 228 + if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 229 + int first = ftrace_global_list == &ftrace_list_end; 230 + add_ftrace_ops(&ftrace_global_list, ops); 231 + ops->flags |= FTRACE_OPS_FL_ENABLED; 232 + if (first) 233 + add_ftrace_ops(&ftrace_ops_list, &global_ops); 234 + } else 235 + add_ftrace_ops(&ftrace_ops_list, ops); 236 + 237 + if (ftrace_enabled) 238 + update_ftrace_function(); 239 + 240 + return 0; 241 + } 242 + 243 + static int __unregister_ftrace_function(struct ftrace_ops *ops) 244 + { 245 + int ret; 246 + 247 + if (ftrace_disabled) 248 + return -ENODEV; 249 + 250 + if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED))) 251 + return -EBUSY; 252 + 253 + if (FTRACE_WARN_ON(ops == &global_ops)) 254 + return -EINVAL; 255 + 256 + if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 257 + ret = remove_ftrace_ops(&ftrace_global_list, ops); 258 + if (!ret && ftrace_global_list == &ftrace_list_end) 259 + ret = remove_ftrace_ops(&ftrace_ops_list, &global_ops); 260 + if (!ret) 261 + ops->flags &= ~FTRACE_OPS_FL_ENABLED; 262 + } else 263 + ret = remove_ftrace_ops(&ftrace_ops_list, ops); 264 + 265 + if (ret < 0) 266 + return ret; 267 + 268 + if (ftrace_enabled) 269 + update_ftrace_function(); 270 + 271 + /* 272 + * Dynamic ops may be freed, we must make sure that all 273 + * callers are done before leaving this function. 274 + */ 275 + if (ops->flags & FTRACE_OPS_FL_DYNAMIC) 276 + synchronize_sched(); 262 277 263 278 return 0; 264 279 } 265 280 266 281 static void ftrace_update_pid_func(void) 267 282 { 268 - ftrace_func_t func; 269 - 283 + /* Only do something if we are tracing something */ 270 284 if (ftrace_trace_function == ftrace_stub) 271 285 return; 272 286 273 - #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 274 - func = ftrace_trace_function; 275 - #else 276 - func = __ftrace_trace_function; 277 - #endif 278 - 279 - if (!list_empty(&ftrace_pids)) { 280 - set_ftrace_pid_function(func); 281 - func = ftrace_pid_func; 282 - } else { 283 - if (func == ftrace_pid_func) 284 - func = ftrace_pid_function; 285 - } 286 - 287 - #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 288 - ftrace_trace_function = func; 289 - #else 290 - __ftrace_trace_function = func; 291 - #endif 287 + update_ftrace_function(); 292 288 } 293 289 294 290 #ifdef CONFIG_FUNCTION_PROFILER ··· 952 888 FTRACE_START_FUNC_RET = (1 << 3), 953 889 FTRACE_STOP_FUNC_RET = (1 << 4), 954 890 }; 891 + struct ftrace_func_entry { 892 + struct hlist_node hlist; 893 + unsigned long ip; 894 + }; 955 895 956 - static int ftrace_filtered; 896 + struct ftrace_hash { 897 + unsigned long size_bits; 898 + struct hlist_head *buckets; 899 + unsigned long count; 900 + struct rcu_head rcu; 901 + }; 902 + 903 + /* 904 + * We make these constant because no one should touch them, 905 + * but they are used as the default "empty hash", to avoid allocating 906 + * it all the time. These are in a read only section such that if 907 + * anyone does try to modify it, it will cause an exception. 908 + */ 909 + static const struct hlist_head empty_buckets[1]; 910 + static const struct ftrace_hash empty_hash = { 911 + .buckets = (struct hlist_head *)empty_buckets, 912 + }; 913 + #define EMPTY_HASH ((struct ftrace_hash *)&empty_hash) 914 + 915 + static struct ftrace_ops global_ops = { 916 + .func = ftrace_stub, 917 + .notrace_hash = EMPTY_HASH, 918 + .filter_hash = EMPTY_HASH, 919 + }; 957 920 958 921 static struct dyn_ftrace *ftrace_new_addrs; 959 922 ··· 1003 912 1004 913 static struct dyn_ftrace *ftrace_free_records; 1005 914 915 + static struct ftrace_func_entry * 916 + ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) 917 + { 918 + unsigned long key; 919 + struct ftrace_func_entry *entry; 920 + struct hlist_head *hhd; 921 + struct hlist_node *n; 922 + 923 + if (!hash->count) 924 + return NULL; 925 + 926 + if (hash->size_bits > 0) 927 + key = hash_long(ip, hash->size_bits); 928 + else 929 + key = 0; 930 + 931 + hhd = &hash->buckets[key]; 932 + 933 + hlist_for_each_entry_rcu(entry, n, hhd, hlist) { 934 + if (entry->ip == ip) 935 + return entry; 936 + } 937 + return NULL; 938 + } 939 + 940 + static void __add_hash_entry(struct ftrace_hash *hash, 941 + struct ftrace_func_entry *entry) 942 + { 943 + struct hlist_head *hhd; 944 + unsigned long key; 945 + 946 + if (hash->size_bits) 947 + key = hash_long(entry->ip, hash->size_bits); 948 + else 949 + key = 0; 950 + 951 + hhd = &hash->buckets[key]; 952 + hlist_add_head(&entry->hlist, hhd); 953 + hash->count++; 954 + } 955 + 956 + static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip) 957 + { 958 + struct ftrace_func_entry *entry; 959 + 960 + entry = kmalloc(sizeof(*entry), GFP_KERNEL); 961 + if (!entry) 962 + return -ENOMEM; 963 + 964 + entry->ip = ip; 965 + __add_hash_entry(hash, entry); 966 + 967 + return 0; 968 + } 969 + 970 + static void 971 + free_hash_entry(struct ftrace_hash *hash, 972 + struct ftrace_func_entry *entry) 973 + { 974 + hlist_del(&entry->hlist); 975 + kfree(entry); 976 + hash->count--; 977 + } 978 + 979 + static void 980 + remove_hash_entry(struct ftrace_hash *hash, 981 + struct ftrace_func_entry *entry) 982 + { 983 + hlist_del(&entry->hlist); 984 + hash->count--; 985 + } 986 + 987 + static void ftrace_hash_clear(struct ftrace_hash *hash) 988 + { 989 + struct hlist_head *hhd; 990 + struct hlist_node *tp, *tn; 991 + struct ftrace_func_entry *entry; 992 + int size = 1 << hash->size_bits; 993 + int i; 994 + 995 + if (!hash->count) 996 + return; 997 + 998 + for (i = 0; i < size; i++) { 999 + hhd = &hash->buckets[i]; 1000 + hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) 1001 + free_hash_entry(hash, entry); 1002 + } 1003 + FTRACE_WARN_ON(hash->count); 1004 + } 1005 + 1006 + static void free_ftrace_hash(struct ftrace_hash *hash) 1007 + { 1008 + if (!hash || hash == EMPTY_HASH) 1009 + return; 1010 + ftrace_hash_clear(hash); 1011 + kfree(hash->buckets); 1012 + kfree(hash); 1013 + } 1014 + 1015 + static void __free_ftrace_hash_rcu(struct rcu_head *rcu) 1016 + { 1017 + struct ftrace_hash *hash; 1018 + 1019 + hash = container_of(rcu, struct ftrace_hash, rcu); 1020 + free_ftrace_hash(hash); 1021 + } 1022 + 1023 + static void free_ftrace_hash_rcu(struct ftrace_hash *hash) 1024 + { 1025 + if (!hash || hash == EMPTY_HASH) 1026 + return; 1027 + call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu); 1028 + } 1029 + 1030 + static struct ftrace_hash *alloc_ftrace_hash(int size_bits) 1031 + { 1032 + struct ftrace_hash *hash; 1033 + int size; 1034 + 1035 + hash = kzalloc(sizeof(*hash), GFP_KERNEL); 1036 + if (!hash) 1037 + return NULL; 1038 + 1039 + size = 1 << size_bits; 1040 + hash->buckets = kzalloc(sizeof(*hash->buckets) * size, GFP_KERNEL); 1041 + 1042 + if (!hash->buckets) { 1043 + kfree(hash); 1044 + return NULL; 1045 + } 1046 + 1047 + hash->size_bits = size_bits; 1048 + 1049 + return hash; 1050 + } 1051 + 1052 + static struct ftrace_hash * 1053 + alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) 1054 + { 1055 + struct ftrace_func_entry *entry; 1056 + struct ftrace_hash *new_hash; 1057 + struct hlist_node *tp; 1058 + int size; 1059 + int ret; 1060 + int i; 1061 + 1062 + new_hash = alloc_ftrace_hash(size_bits); 1063 + if (!new_hash) 1064 + return NULL; 1065 + 1066 + /* Empty hash? */ 1067 + if (!hash || !hash->count) 1068 + return new_hash; 1069 + 1070 + size = 1 << hash->size_bits; 1071 + for (i = 0; i < size; i++) { 1072 + hlist_for_each_entry(entry, tp, &hash->buckets[i], hlist) { 1073 + ret = add_hash_entry(new_hash, entry->ip); 1074 + if (ret < 0) 1075 + goto free_hash; 1076 + } 1077 + } 1078 + 1079 + FTRACE_WARN_ON(new_hash->count != hash->count); 1080 + 1081 + return new_hash; 1082 + 1083 + free_hash: 1084 + free_ftrace_hash(new_hash); 1085 + return NULL; 1086 + } 1087 + 1088 + static int 1089 + ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src) 1090 + { 1091 + struct ftrace_func_entry *entry; 1092 + struct hlist_node *tp, *tn; 1093 + struct hlist_head *hhd; 1094 + struct ftrace_hash *old_hash; 1095 + struct ftrace_hash *new_hash; 1096 + unsigned long key; 1097 + int size = src->count; 1098 + int bits = 0; 1099 + int i; 1100 + 1101 + /* 1102 + * If the new source is empty, just free dst and assign it 1103 + * the empty_hash. 1104 + */ 1105 + if (!src->count) { 1106 + free_ftrace_hash_rcu(*dst); 1107 + rcu_assign_pointer(*dst, EMPTY_HASH); 1108 + return 0; 1109 + } 1110 + 1111 + /* 1112 + * Make the hash size about 1/2 the # found 1113 + */ 1114 + for (size /= 2; size; size >>= 1) 1115 + bits++; 1116 + 1117 + /* Don't allocate too much */ 1118 + if (bits > FTRACE_HASH_MAX_BITS) 1119 + bits = FTRACE_HASH_MAX_BITS; 1120 + 1121 + new_hash = alloc_ftrace_hash(bits); 1122 + if (!new_hash) 1123 + return -ENOMEM; 1124 + 1125 + size = 1 << src->size_bits; 1126 + for (i = 0; i < size; i++) { 1127 + hhd = &src->buckets[i]; 1128 + hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) { 1129 + if (bits > 0) 1130 + key = hash_long(entry->ip, bits); 1131 + else 1132 + key = 0; 1133 + remove_hash_entry(src, entry); 1134 + __add_hash_entry(new_hash, entry); 1135 + } 1136 + } 1137 + 1138 + old_hash = *dst; 1139 + rcu_assign_pointer(*dst, new_hash); 1140 + free_ftrace_hash_rcu(old_hash); 1141 + 1142 + return 0; 1143 + } 1144 + 1145 + /* 1146 + * Test the hashes for this ops to see if we want to call 1147 + * the ops->func or not. 1148 + * 1149 + * It's a match if the ip is in the ops->filter_hash or 1150 + * the filter_hash does not exist or is empty, 1151 + * AND 1152 + * the ip is not in the ops->notrace_hash. 1153 + * 1154 + * This needs to be called with preemption disabled as 1155 + * the hashes are freed with call_rcu_sched(). 1156 + */ 1157 + static int 1158 + ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) 1159 + { 1160 + struct ftrace_hash *filter_hash; 1161 + struct ftrace_hash *notrace_hash; 1162 + int ret; 1163 + 1164 + filter_hash = rcu_dereference_raw(ops->filter_hash); 1165 + notrace_hash = rcu_dereference_raw(ops->notrace_hash); 1166 + 1167 + if ((!filter_hash || !filter_hash->count || 1168 + ftrace_lookup_ip(filter_hash, ip)) && 1169 + (!notrace_hash || !notrace_hash->count || 1170 + !ftrace_lookup_ip(notrace_hash, ip))) 1171 + ret = 1; 1172 + else 1173 + ret = 0; 1174 + 1175 + return ret; 1176 + } 1177 + 1006 1178 /* 1007 1179 * This is a double for. Do not use 'break' to break out of the loop, 1008 1180 * you must use a goto. ··· 1279 925 #define while_for_each_ftrace_rec() \ 1280 926 } \ 1281 927 } 928 + 929 + static void __ftrace_hash_rec_update(struct ftrace_ops *ops, 930 + int filter_hash, 931 + bool inc) 932 + { 933 + struct ftrace_hash *hash; 934 + struct ftrace_hash *other_hash; 935 + struct ftrace_page *pg; 936 + struct dyn_ftrace *rec; 937 + int count = 0; 938 + int all = 0; 939 + 940 + /* Only update if the ops has been registered */ 941 + if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) 942 + return; 943 + 944 + /* 945 + * In the filter_hash case: 946 + * If the count is zero, we update all records. 947 + * Otherwise we just update the items in the hash. 948 + * 949 + * In the notrace_hash case: 950 + * We enable the update in the hash. 951 + * As disabling notrace means enabling the tracing, 952 + * and enabling notrace means disabling, the inc variable 953 + * gets inversed. 954 + */ 955 + if (filter_hash) { 956 + hash = ops->filter_hash; 957 + other_hash = ops->notrace_hash; 958 + if (!hash || !hash->count) 959 + all = 1; 960 + } else { 961 + inc = !inc; 962 + hash = ops->notrace_hash; 963 + other_hash = ops->filter_hash; 964 + /* 965 + * If the notrace hash has no items, 966 + * then there's nothing to do. 967 + */ 968 + if (hash && !hash->count) 969 + return; 970 + } 971 + 972 + do_for_each_ftrace_rec(pg, rec) { 973 + int in_other_hash = 0; 974 + int in_hash = 0; 975 + int match = 0; 976 + 977 + if (all) { 978 + /* 979 + * Only the filter_hash affects all records. 980 + * Update if the record is not in the notrace hash. 981 + */ 982 + if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip)) 983 + match = 1; 984 + } else { 985 + in_hash = hash && !!ftrace_lookup_ip(hash, rec->ip); 986 + in_other_hash = other_hash && !!ftrace_lookup_ip(other_hash, rec->ip); 987 + 988 + /* 989 + * 990 + */ 991 + if (filter_hash && in_hash && !in_other_hash) 992 + match = 1; 993 + else if (!filter_hash && in_hash && 994 + (in_other_hash || !other_hash->count)) 995 + match = 1; 996 + } 997 + if (!match) 998 + continue; 999 + 1000 + if (inc) { 1001 + rec->flags++; 1002 + if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX)) 1003 + return; 1004 + } else { 1005 + if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0)) 1006 + return; 1007 + rec->flags--; 1008 + } 1009 + count++; 1010 + /* Shortcut, if we handled all records, we are done. */ 1011 + if (!all && count == hash->count) 1012 + return; 1013 + } while_for_each_ftrace_rec(); 1014 + } 1015 + 1016 + static void ftrace_hash_rec_disable(struct ftrace_ops *ops, 1017 + int filter_hash) 1018 + { 1019 + __ftrace_hash_rec_update(ops, filter_hash, 0); 1020 + } 1021 + 1022 + static void ftrace_hash_rec_enable(struct ftrace_ops *ops, 1023 + int filter_hash) 1024 + { 1025 + __ftrace_hash_rec_update(ops, filter_hash, 1); 1026 + } 1282 1027 1283 1028 static void ftrace_free_rec(struct dyn_ftrace *rec) 1284 1029 { ··· 1500 1047 ftrace_addr = (unsigned long)FTRACE_ADDR; 1501 1048 1502 1049 /* 1503 - * If this record is not to be traced or we want to disable it, 1504 - * then disable it. 1050 + * If we are enabling tracing: 1505 1051 * 1506 - * If we want to enable it and filtering is off, then enable it. 1052 + * If the record has a ref count, then we need to enable it 1053 + * because someone is using it. 1507 1054 * 1508 - * If we want to enable it and filtering is on, enable it only if 1509 - * it's filtered 1055 + * Otherwise we make sure its disabled. 1056 + * 1057 + * If we are disabling tracing, then disable all records that 1058 + * are enabled. 1510 1059 */ 1511 - if (enable && !(rec->flags & FTRACE_FL_NOTRACE)) { 1512 - if (!ftrace_filtered || (rec->flags & FTRACE_FL_FILTER)) 1513 - flag = FTRACE_FL_ENABLED; 1514 - } 1060 + if (enable && (rec->flags & ~FTRACE_FL_MASK)) 1061 + flag = FTRACE_FL_ENABLED; 1515 1062 1516 1063 /* If the state of this record hasn't changed, then do nothing */ 1517 1064 if ((rec->flags & FTRACE_FL_ENABLED) == flag) ··· 1532 1079 struct ftrace_page *pg; 1533 1080 int failed; 1534 1081 1082 + if (unlikely(ftrace_disabled)) 1083 + return; 1084 + 1535 1085 do_for_each_ftrace_rec(pg, rec) { 1536 - /* 1537 - * Skip over free records, records that have 1538 - * failed and not converted. 1539 - */ 1540 - if (rec->flags & FTRACE_FL_FREE || 1541 - rec->flags & FTRACE_FL_FAILED || 1542 - !(rec->flags & FTRACE_FL_CONVERTED)) 1086 + /* Skip over free records */ 1087 + if (rec->flags & FTRACE_FL_FREE) 1543 1088 continue; 1544 1089 1545 1090 failed = __ftrace_replace_code(rec, enable); 1546 1091 if (failed) { 1547 - rec->flags |= FTRACE_FL_FAILED; 1548 1092 ftrace_bug(failed, rec->ip); 1549 1093 /* Stop processing */ 1550 1094 return; ··· 1557 1107 1558 1108 ip = rec->ip; 1559 1109 1110 + if (unlikely(ftrace_disabled)) 1111 + return 0; 1112 + 1560 1113 ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR); 1561 1114 if (ret) { 1562 1115 ftrace_bug(ret, ip); 1563 - rec->flags |= FTRACE_FL_FAILED; 1564 1116 return 0; 1565 1117 } 1566 1118 return 1; ··· 1623 1171 1624 1172 static ftrace_func_t saved_ftrace_func; 1625 1173 static int ftrace_start_up; 1174 + static int global_start_up; 1626 1175 1627 1176 static void ftrace_startup_enable(int command) 1628 1177 { ··· 1638 1185 ftrace_run_update_code(command); 1639 1186 } 1640 1187 1641 - static void ftrace_startup(int command) 1188 + static void ftrace_startup(struct ftrace_ops *ops, int command) 1642 1189 { 1190 + bool hash_enable = true; 1191 + 1643 1192 if (unlikely(ftrace_disabled)) 1644 1193 return; 1645 1194 1646 1195 ftrace_start_up++; 1647 1196 command |= FTRACE_ENABLE_CALLS; 1648 1197 1198 + /* ops marked global share the filter hashes */ 1199 + if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 1200 + ops = &global_ops; 1201 + /* Don't update hash if global is already set */ 1202 + if (global_start_up) 1203 + hash_enable = false; 1204 + global_start_up++; 1205 + } 1206 + 1207 + ops->flags |= FTRACE_OPS_FL_ENABLED; 1208 + if (hash_enable) 1209 + ftrace_hash_rec_enable(ops, 1); 1210 + 1649 1211 ftrace_startup_enable(command); 1650 1212 } 1651 1213 1652 - static void ftrace_shutdown(int command) 1214 + static void ftrace_shutdown(struct ftrace_ops *ops, int command) 1653 1215 { 1216 + bool hash_disable = true; 1217 + 1654 1218 if (unlikely(ftrace_disabled)) 1655 1219 return; 1656 1220 ··· 1678 1208 * further ftrace uses. 1679 1209 */ 1680 1210 WARN_ON_ONCE(ftrace_start_up < 0); 1211 + 1212 + if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 1213 + ops = &global_ops; 1214 + global_start_up--; 1215 + WARN_ON_ONCE(global_start_up < 0); 1216 + /* Don't update hash if global still has users */ 1217 + if (global_start_up) { 1218 + WARN_ON_ONCE(!ftrace_start_up); 1219 + hash_disable = false; 1220 + } 1221 + } 1222 + 1223 + if (hash_disable) 1224 + ftrace_hash_rec_disable(ops, 1); 1225 + 1226 + if (ops != &global_ops || !global_start_up) 1227 + ops->flags &= ~FTRACE_OPS_FL_ENABLED; 1681 1228 1682 1229 if (!ftrace_start_up) 1683 1230 command |= FTRACE_DISABLE_CALLS; ··· 1760 1273 */ 1761 1274 if (!ftrace_code_disable(mod, p)) { 1762 1275 ftrace_free_rec(p); 1763 - continue; 1276 + /* Game over */ 1277 + break; 1764 1278 } 1765 1279 1766 - p->flags |= FTRACE_FL_CONVERTED; 1767 1280 ftrace_update_cnt++; 1768 1281 1769 1282 /* ··· 1838 1351 enum { 1839 1352 FTRACE_ITER_FILTER = (1 << 0), 1840 1353 FTRACE_ITER_NOTRACE = (1 << 1), 1841 - FTRACE_ITER_FAILURES = (1 << 2), 1842 - FTRACE_ITER_PRINTALL = (1 << 3), 1843 - FTRACE_ITER_HASH = (1 << 4), 1354 + FTRACE_ITER_PRINTALL = (1 << 2), 1355 + FTRACE_ITER_HASH = (1 << 3), 1356 + FTRACE_ITER_ENABLED = (1 << 4), 1844 1357 }; 1845 1358 1846 1359 #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ ··· 1852 1365 struct dyn_ftrace *func; 1853 1366 struct ftrace_func_probe *probe; 1854 1367 struct trace_parser parser; 1368 + struct ftrace_hash *hash; 1369 + struct ftrace_ops *ops; 1855 1370 int hidx; 1856 1371 int idx; 1857 1372 unsigned flags; ··· 1950 1461 t_next(struct seq_file *m, void *v, loff_t *pos) 1951 1462 { 1952 1463 struct ftrace_iterator *iter = m->private; 1464 + struct ftrace_ops *ops = &global_ops; 1953 1465 struct dyn_ftrace *rec = NULL; 1466 + 1467 + if (unlikely(ftrace_disabled)) 1468 + return NULL; 1954 1469 1955 1470 if (iter->flags & FTRACE_ITER_HASH) 1956 1471 return t_hash_next(m, pos); ··· 1976 1483 rec = &iter->pg->records[iter->idx++]; 1977 1484 if ((rec->flags & FTRACE_FL_FREE) || 1978 1485 1979 - (!(iter->flags & FTRACE_ITER_FAILURES) && 1980 - (rec->flags & FTRACE_FL_FAILED)) || 1981 - 1982 - ((iter->flags & FTRACE_ITER_FAILURES) && 1983 - !(rec->flags & FTRACE_FL_FAILED)) || 1984 - 1985 1486 ((iter->flags & FTRACE_ITER_FILTER) && 1986 - !(rec->flags & FTRACE_FL_FILTER)) || 1487 + !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) || 1987 1488 1988 1489 ((iter->flags & FTRACE_ITER_NOTRACE) && 1989 - !(rec->flags & FTRACE_FL_NOTRACE))) { 1490 + !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || 1491 + 1492 + ((iter->flags & FTRACE_ITER_ENABLED) && 1493 + !(rec->flags & ~FTRACE_FL_MASK))) { 1494 + 1990 1495 rec = NULL; 1991 1496 goto retry; 1992 1497 } ··· 2008 1517 static void *t_start(struct seq_file *m, loff_t *pos) 2009 1518 { 2010 1519 struct ftrace_iterator *iter = m->private; 1520 + struct ftrace_ops *ops = &global_ops; 2011 1521 void *p = NULL; 2012 1522 loff_t l; 2013 1523 2014 1524 mutex_lock(&ftrace_lock); 1525 + 1526 + if (unlikely(ftrace_disabled)) 1527 + return NULL; 1528 + 2015 1529 /* 2016 1530 * If an lseek was done, then reset and start from beginning. 2017 1531 */ ··· 2028 1532 * off, we can short cut and just print out that all 2029 1533 * functions are enabled. 2030 1534 */ 2031 - if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) { 1535 + if (iter->flags & FTRACE_ITER_FILTER && !ops->filter_hash->count) { 2032 1536 if (*pos > 0) 2033 1537 return t_hash_start(m, pos); 2034 1538 iter->flags |= FTRACE_ITER_PRINTALL; ··· 2086 1590 if (!rec) 2087 1591 return 0; 2088 1592 2089 - seq_printf(m, "%ps\n", (void *)rec->ip); 1593 + seq_printf(m, "%ps", (void *)rec->ip); 1594 + if (iter->flags & FTRACE_ITER_ENABLED) 1595 + seq_printf(m, " (%ld)", 1596 + rec->flags & ~FTRACE_FL_MASK); 1597 + seq_printf(m, "\n"); 2090 1598 2091 1599 return 0; 2092 1600 } ··· 2130 1630 } 2131 1631 2132 1632 static int 2133 - ftrace_failures_open(struct inode *inode, struct file *file) 1633 + ftrace_enabled_open(struct inode *inode, struct file *file) 2134 1634 { 2135 - int ret; 2136 - struct seq_file *m; 2137 1635 struct ftrace_iterator *iter; 1636 + int ret; 2138 1637 2139 - ret = ftrace_avail_open(inode, file); 1638 + if (unlikely(ftrace_disabled)) 1639 + return -ENODEV; 1640 + 1641 + iter = kzalloc(sizeof(*iter), GFP_KERNEL); 1642 + if (!iter) 1643 + return -ENOMEM; 1644 + 1645 + iter->pg = ftrace_pages_start; 1646 + iter->flags = FTRACE_ITER_ENABLED; 1647 + 1648 + ret = seq_open(file, &show_ftrace_seq_ops); 2140 1649 if (!ret) { 2141 - m = file->private_data; 2142 - iter = m->private; 2143 - iter->flags = FTRACE_ITER_FAILURES; 1650 + struct seq_file *m = file->private_data; 1651 + 1652 + m->private = iter; 1653 + } else { 1654 + kfree(iter); 2144 1655 } 2145 1656 2146 1657 return ret; 2147 1658 } 2148 1659 2149 - 2150 - static void ftrace_filter_reset(int enable) 1660 + static void ftrace_filter_reset(struct ftrace_hash *hash) 2151 1661 { 2152 - struct ftrace_page *pg; 2153 - struct dyn_ftrace *rec; 2154 - unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 2155 - 2156 1662 mutex_lock(&ftrace_lock); 2157 - if (enable) 2158 - ftrace_filtered = 0; 2159 - do_for_each_ftrace_rec(pg, rec) { 2160 - if (rec->flags & FTRACE_FL_FAILED) 2161 - continue; 2162 - rec->flags &= ~type; 2163 - } while_for_each_ftrace_rec(); 1663 + ftrace_hash_clear(hash); 2164 1664 mutex_unlock(&ftrace_lock); 2165 1665 } 2166 1666 2167 1667 static int 2168 - ftrace_regex_open(struct inode *inode, struct file *file, int enable) 1668 + ftrace_regex_open(struct ftrace_ops *ops, int flag, 1669 + struct inode *inode, struct file *file) 2169 1670 { 2170 1671 struct ftrace_iterator *iter; 1672 + struct ftrace_hash *hash; 2171 1673 int ret = 0; 2172 1674 2173 1675 if (unlikely(ftrace_disabled)) ··· 2184 1682 return -ENOMEM; 2185 1683 } 2186 1684 1685 + if (flag & FTRACE_ITER_NOTRACE) 1686 + hash = ops->notrace_hash; 1687 + else 1688 + hash = ops->filter_hash; 1689 + 1690 + iter->ops = ops; 1691 + iter->flags = flag; 1692 + 1693 + if (file->f_mode & FMODE_WRITE) { 1694 + mutex_lock(&ftrace_lock); 1695 + iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); 1696 + mutex_unlock(&ftrace_lock); 1697 + 1698 + if (!iter->hash) { 1699 + trace_parser_put(&iter->parser); 1700 + kfree(iter); 1701 + return -ENOMEM; 1702 + } 1703 + } 1704 + 2187 1705 mutex_lock(&ftrace_regex_lock); 1706 + 2188 1707 if ((file->f_mode & FMODE_WRITE) && 2189 1708 (file->f_flags & O_TRUNC)) 2190 - ftrace_filter_reset(enable); 1709 + ftrace_filter_reset(iter->hash); 2191 1710 2192 1711 if (file->f_mode & FMODE_READ) { 2193 1712 iter->pg = ftrace_pages_start; 2194 - iter->flags = enable ? FTRACE_ITER_FILTER : 2195 - FTRACE_ITER_NOTRACE; 2196 1713 2197 1714 ret = seq_open(file, &show_ftrace_seq_ops); 2198 1715 if (!ret) { 2199 1716 struct seq_file *m = file->private_data; 2200 1717 m->private = iter; 2201 1718 } else { 1719 + /* Failed */ 1720 + free_ftrace_hash(iter->hash); 2202 1721 trace_parser_put(&iter->parser); 2203 1722 kfree(iter); 2204 1723 } ··· 2233 1710 static int 2234 1711 ftrace_filter_open(struct inode *inode, struct file *file) 2235 1712 { 2236 - return ftrace_regex_open(inode, file, 1); 1713 + return ftrace_regex_open(&global_ops, FTRACE_ITER_FILTER, 1714 + inode, file); 2237 1715 } 2238 1716 2239 1717 static int 2240 1718 ftrace_notrace_open(struct inode *inode, struct file *file) 2241 1719 { 2242 - return ftrace_regex_open(inode, file, 0); 1720 + return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE, 1721 + inode, file); 2243 1722 } 2244 1723 2245 1724 static loff_t ··· 2286 1761 } 2287 1762 2288 1763 static int 2289 - ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type) 1764 + enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not) 2290 1765 { 2291 - char str[KSYM_SYMBOL_LEN]; 1766 + struct ftrace_func_entry *entry; 1767 + int ret = 0; 2292 1768 2293 - kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); 2294 - return ftrace_match(str, regex, len, type); 2295 - } 1769 + entry = ftrace_lookup_ip(hash, rec->ip); 1770 + if (not) { 1771 + /* Do nothing if it doesn't exist */ 1772 + if (!entry) 1773 + return 0; 2296 1774 2297 - static int ftrace_match_records(char *buff, int len, int enable) 2298 - { 2299 - unsigned int search_len; 2300 - struct ftrace_page *pg; 2301 - struct dyn_ftrace *rec; 2302 - unsigned long flag; 2303 - char *search; 2304 - int type; 2305 - int not; 2306 - int found = 0; 1775 + free_hash_entry(hash, entry); 1776 + } else { 1777 + /* Do nothing if it exists */ 1778 + if (entry) 1779 + return 0; 2307 1780 2308 - flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 2309 - type = filter_parse_regex(buff, len, &search, &not); 2310 - 2311 - search_len = strlen(search); 2312 - 2313 - mutex_lock(&ftrace_lock); 2314 - do_for_each_ftrace_rec(pg, rec) { 2315 - 2316 - if (rec->flags & FTRACE_FL_FAILED) 2317 - continue; 2318 - 2319 - if (ftrace_match_record(rec, search, search_len, type)) { 2320 - if (not) 2321 - rec->flags &= ~flag; 2322 - else 2323 - rec->flags |= flag; 2324 - found = 1; 2325 - } 2326 - /* 2327 - * Only enable filtering if we have a function that 2328 - * is filtered on. 2329 - */ 2330 - if (enable && (rec->flags & FTRACE_FL_FILTER)) 2331 - ftrace_filtered = 1; 2332 - } while_for_each_ftrace_rec(); 2333 - mutex_unlock(&ftrace_lock); 2334 - 2335 - return found; 1781 + ret = add_hash_entry(hash, rec->ip); 1782 + } 1783 + return ret; 2336 1784 } 2337 1785 2338 1786 static int 2339 - ftrace_match_module_record(struct dyn_ftrace *rec, char *mod, 2340 - char *regex, int len, int type) 1787 + ftrace_match_record(struct dyn_ftrace *rec, char *mod, 1788 + char *regex, int len, int type) 2341 1789 { 2342 1790 char str[KSYM_SYMBOL_LEN]; 2343 1791 char *modname; 2344 1792 2345 1793 kallsyms_lookup(rec->ip, NULL, NULL, &modname, str); 2346 1794 2347 - if (!modname || strcmp(modname, mod)) 2348 - return 0; 1795 + if (mod) { 1796 + /* module lookup requires matching the module */ 1797 + if (!modname || strcmp(modname, mod)) 1798 + return 0; 2349 1799 2350 - /* blank search means to match all funcs in the mod */ 2351 - if (len) 2352 - return ftrace_match(str, regex, len, type); 2353 - else 2354 - return 1; 1800 + /* blank search means to match all funcs in the mod */ 1801 + if (!len) 1802 + return 1; 1803 + } 1804 + 1805 + return ftrace_match(str, regex, len, type); 2355 1806 } 2356 1807 2357 - static int ftrace_match_module_records(char *buff, char *mod, int enable) 1808 + static int 1809 + match_records(struct ftrace_hash *hash, char *buff, 1810 + int len, char *mod, int not) 2358 1811 { 2359 1812 unsigned search_len = 0; 2360 1813 struct ftrace_page *pg; 2361 1814 struct dyn_ftrace *rec; 2362 1815 int type = MATCH_FULL; 2363 1816 char *search = buff; 2364 - unsigned long flag; 2365 - int not = 0; 2366 1817 int found = 0; 1818 + int ret; 2367 1819 2368 - flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 1820 + if (len) { 1821 + type = filter_parse_regex(buff, len, &search, &not); 1822 + search_len = strlen(search); 1823 + } 1824 + 1825 + mutex_lock(&ftrace_lock); 1826 + 1827 + if (unlikely(ftrace_disabled)) 1828 + goto out_unlock; 1829 + 1830 + do_for_each_ftrace_rec(pg, rec) { 1831 + 1832 + if (ftrace_match_record(rec, mod, search, search_len, type)) { 1833 + ret = enter_record(hash, rec, not); 1834 + if (ret < 0) { 1835 + found = ret; 1836 + goto out_unlock; 1837 + } 1838 + found = 1; 1839 + } 1840 + } while_for_each_ftrace_rec(); 1841 + out_unlock: 1842 + mutex_unlock(&ftrace_lock); 1843 + 1844 + return found; 1845 + } 1846 + 1847 + static int 1848 + ftrace_match_records(struct ftrace_hash *hash, char *buff, int len) 1849 + { 1850 + return match_records(hash, buff, len, NULL, 0); 1851 + } 1852 + 1853 + static int 1854 + ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod) 1855 + { 1856 + int not = 0; 2369 1857 2370 1858 /* blank or '*' mean the same */ 2371 1859 if (strcmp(buff, "*") == 0) ··· 2390 1852 not = 1; 2391 1853 } 2392 1854 2393 - if (strlen(buff)) { 2394 - type = filter_parse_regex(buff, strlen(buff), &search, &not); 2395 - search_len = strlen(search); 2396 - } 2397 - 2398 - mutex_lock(&ftrace_lock); 2399 - do_for_each_ftrace_rec(pg, rec) { 2400 - 2401 - if (rec->flags & FTRACE_FL_FAILED) 2402 - continue; 2403 - 2404 - if (ftrace_match_module_record(rec, mod, 2405 - search, search_len, type)) { 2406 - if (not) 2407 - rec->flags &= ~flag; 2408 - else 2409 - rec->flags |= flag; 2410 - found = 1; 2411 - } 2412 - if (enable && (rec->flags & FTRACE_FL_FILTER)) 2413 - ftrace_filtered = 1; 2414 - 2415 - } while_for_each_ftrace_rec(); 2416 - mutex_unlock(&ftrace_lock); 2417 - 2418 - return found; 1855 + return match_records(hash, buff, strlen(buff), mod, not); 2419 1856 } 2420 1857 2421 1858 /* ··· 2401 1888 static int 2402 1889 ftrace_mod_callback(char *func, char *cmd, char *param, int enable) 2403 1890 { 1891 + struct ftrace_ops *ops = &global_ops; 1892 + struct ftrace_hash *hash; 2404 1893 char *mod; 1894 + int ret = -EINVAL; 2405 1895 2406 1896 /* 2407 1897 * cmd == 'mod' because we only registered this func ··· 2416 1900 2417 1901 /* we must have a module name */ 2418 1902 if (!param) 2419 - return -EINVAL; 1903 + return ret; 2420 1904 2421 1905 mod = strsep(&param, ":"); 2422 1906 if (!strlen(mod)) 2423 - return -EINVAL; 1907 + return ret; 2424 1908 2425 - if (ftrace_match_module_records(func, mod, enable)) 2426 - return 0; 2427 - return -EINVAL; 1909 + if (enable) 1910 + hash = ops->filter_hash; 1911 + else 1912 + hash = ops->notrace_hash; 1913 + 1914 + ret = ftrace_match_module_records(hash, func, mod); 1915 + if (!ret) 1916 + ret = -EINVAL; 1917 + if (ret < 0) 1918 + return ret; 1919 + 1920 + return 0; 2428 1921 } 2429 1922 2430 1923 static struct ftrace_func_command ftrace_mod_cmd = { ··· 2484 1959 2485 1960 static void __enable_ftrace_function_probe(void) 2486 1961 { 1962 + int ret; 2487 1963 int i; 2488 1964 2489 1965 if (ftrace_probe_registered) ··· 2499 1973 if (i == FTRACE_FUNC_HASHSIZE) 2500 1974 return; 2501 1975 2502 - __register_ftrace_function(&trace_probe_ops); 2503 - ftrace_startup(0); 1976 + ret = __register_ftrace_function(&trace_probe_ops); 1977 + if (!ret) 1978 + ftrace_startup(&trace_probe_ops, 0); 1979 + 2504 1980 ftrace_probe_registered = 1; 2505 1981 } 2506 1982 2507 1983 static void __disable_ftrace_function_probe(void) 2508 1984 { 1985 + int ret; 2509 1986 int i; 2510 1987 2511 1988 if (!ftrace_probe_registered) ··· 2521 1992 } 2522 1993 2523 1994 /* no more funcs left */ 2524 - __unregister_ftrace_function(&trace_probe_ops); 2525 - ftrace_shutdown(0); 1995 + ret = __unregister_ftrace_function(&trace_probe_ops); 1996 + if (!ret) 1997 + ftrace_shutdown(&trace_probe_ops, 0); 1998 + 2526 1999 ftrace_probe_registered = 0; 2527 2000 } 2528 2001 ··· 2560 2029 return -EINVAL; 2561 2030 2562 2031 mutex_lock(&ftrace_lock); 2032 + 2033 + if (unlikely(ftrace_disabled)) 2034 + goto out_unlock; 2035 + 2563 2036 do_for_each_ftrace_rec(pg, rec) { 2564 2037 2565 - if (rec->flags & FTRACE_FL_FAILED) 2566 - continue; 2567 - 2568 - if (!ftrace_match_record(rec, search, len, type)) 2038 + if (!ftrace_match_record(rec, NULL, search, len, type)) 2569 2039 continue; 2570 2040 2571 2041 entry = kmalloc(sizeof(*entry), GFP_KERNEL); ··· 2727 2195 return ret; 2728 2196 } 2729 2197 2730 - static int ftrace_process_regex(char *buff, int len, int enable) 2198 + static int ftrace_process_regex(struct ftrace_hash *hash, 2199 + char *buff, int len, int enable) 2731 2200 { 2732 2201 char *func, *command, *next = buff; 2733 2202 struct ftrace_func_command *p; 2734 - int ret = -EINVAL; 2203 + int ret; 2735 2204 2736 2205 func = strsep(&next, ":"); 2737 2206 2738 2207 if (!next) { 2739 - if (ftrace_match_records(func, len, enable)) 2740 - return 0; 2741 - return ret; 2208 + ret = ftrace_match_records(hash, func, len); 2209 + if (!ret) 2210 + ret = -EINVAL; 2211 + if (ret < 0) 2212 + return ret; 2213 + return 0; 2742 2214 } 2743 2215 2744 2216 /* command found */ ··· 2775 2239 2776 2240 mutex_lock(&ftrace_regex_lock); 2777 2241 2242 + ret = -ENODEV; 2243 + if (unlikely(ftrace_disabled)) 2244 + goto out_unlock; 2245 + 2778 2246 if (file->f_mode & FMODE_READ) { 2779 2247 struct seq_file *m = file->private_data; 2780 2248 iter = m->private; ··· 2790 2250 2791 2251 if (read >= 0 && trace_parser_loaded(parser) && 2792 2252 !trace_parser_cont(parser)) { 2793 - ret = ftrace_process_regex(parser->buffer, 2253 + ret = ftrace_process_regex(iter->hash, parser->buffer, 2794 2254 parser->idx, enable); 2795 2255 trace_parser_clear(parser); 2796 2256 if (ret) ··· 2818 2278 return ftrace_regex_write(file, ubuf, cnt, ppos, 0); 2819 2279 } 2820 2280 2821 - static void 2822 - ftrace_set_regex(unsigned char *buf, int len, int reset, int enable) 2281 + static int 2282 + ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, 2283 + int reset, int enable) 2823 2284 { 2285 + struct ftrace_hash **orig_hash; 2286 + struct ftrace_hash *hash; 2287 + int ret; 2288 + 2289 + /* All global ops uses the global ops filters */ 2290 + if (ops->flags & FTRACE_OPS_FL_GLOBAL) 2291 + ops = &global_ops; 2292 + 2824 2293 if (unlikely(ftrace_disabled)) 2825 - return; 2294 + return -ENODEV; 2295 + 2296 + if (enable) 2297 + orig_hash = &ops->filter_hash; 2298 + else 2299 + orig_hash = &ops->notrace_hash; 2300 + 2301 + hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 2302 + if (!hash) 2303 + return -ENOMEM; 2826 2304 2827 2305 mutex_lock(&ftrace_regex_lock); 2828 2306 if (reset) 2829 - ftrace_filter_reset(enable); 2307 + ftrace_filter_reset(hash); 2830 2308 if (buf) 2831 - ftrace_match_records(buf, len, enable); 2309 + ftrace_match_records(hash, buf, len); 2310 + 2311 + mutex_lock(&ftrace_lock); 2312 + ret = ftrace_hash_move(orig_hash, hash); 2313 + mutex_unlock(&ftrace_lock); 2314 + 2832 2315 mutex_unlock(&ftrace_regex_lock); 2316 + 2317 + free_ftrace_hash(hash); 2318 + return ret; 2833 2319 } 2834 2320 2835 2321 /** 2836 2322 * ftrace_set_filter - set a function to filter on in ftrace 2323 + * @ops - the ops to set the filter with 2837 2324 * @buf - the string that holds the function filter text. 2838 2325 * @len - the length of the string. 2839 2326 * @reset - non zero to reset all filters before applying this filter. ··· 2868 2301 * Filters denote which functions should be enabled when tracing is enabled. 2869 2302 * If @buf is NULL and reset is set, all functions will be enabled for tracing. 2870 2303 */ 2871 - void ftrace_set_filter(unsigned char *buf, int len, int reset) 2304 + void ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, 2305 + int len, int reset) 2872 2306 { 2873 - ftrace_set_regex(buf, len, reset, 1); 2307 + ftrace_set_regex(ops, buf, len, reset, 1); 2874 2308 } 2309 + EXPORT_SYMBOL_GPL(ftrace_set_filter); 2875 2310 2876 2311 /** 2877 2312 * ftrace_set_notrace - set a function to not trace in ftrace 2313 + * @ops - the ops to set the notrace filter with 2878 2314 * @buf - the string that holds the function notrace text. 2879 2315 * @len - the length of the string. 2880 2316 * @reset - non zero to reset all filters before applying this filter. ··· 2886 2316 * is enabled. If @buf is NULL and reset is set, all functions will be enabled 2887 2317 * for tracing. 2888 2318 */ 2889 - void ftrace_set_notrace(unsigned char *buf, int len, int reset) 2319 + void ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, 2320 + int len, int reset) 2890 2321 { 2891 - ftrace_set_regex(buf, len, reset, 0); 2322 + ftrace_set_regex(ops, buf, len, reset, 0); 2892 2323 } 2324 + EXPORT_SYMBOL_GPL(ftrace_set_notrace); 2325 + /** 2326 + * ftrace_set_filter - set a function to filter on in ftrace 2327 + * @ops - the ops to set the filter with 2328 + * @buf - the string that holds the function filter text. 2329 + * @len - the length of the string. 2330 + * @reset - non zero to reset all filters before applying this filter. 2331 + * 2332 + * Filters denote which functions should be enabled when tracing is enabled. 2333 + * If @buf is NULL and reset is set, all functions will be enabled for tracing. 2334 + */ 2335 + void ftrace_set_global_filter(unsigned char *buf, int len, int reset) 2336 + { 2337 + ftrace_set_regex(&global_ops, buf, len, reset, 1); 2338 + } 2339 + EXPORT_SYMBOL_GPL(ftrace_set_global_filter); 2340 + 2341 + /** 2342 + * ftrace_set_notrace - set a function to not trace in ftrace 2343 + * @ops - the ops to set the notrace filter with 2344 + * @buf - the string that holds the function notrace text. 2345 + * @len - the length of the string. 2346 + * @reset - non zero to reset all filters before applying this filter. 2347 + * 2348 + * Notrace Filters denote which functions should not be enabled when tracing 2349 + * is enabled. If @buf is NULL and reset is set, all functions will be enabled 2350 + * for tracing. 2351 + */ 2352 + void ftrace_set_global_notrace(unsigned char *buf, int len, int reset) 2353 + { 2354 + ftrace_set_regex(&global_ops, buf, len, reset, 0); 2355 + } 2356 + EXPORT_SYMBOL_GPL(ftrace_set_global_notrace); 2893 2357 2894 2358 /* 2895 2359 * command line interface to allow users to set filters on boot up. ··· 2974 2370 } 2975 2371 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 2976 2372 2977 - static void __init set_ftrace_early_filter(char *buf, int enable) 2373 + static void __init 2374 + set_ftrace_early_filter(struct ftrace_ops *ops, char *buf, int enable) 2978 2375 { 2979 2376 char *func; 2980 2377 2981 2378 while (buf) { 2982 2379 func = strsep(&buf, ","); 2983 - ftrace_set_regex(func, strlen(func), 0, enable); 2380 + ftrace_set_regex(ops, func, strlen(func), 0, enable); 2984 2381 } 2985 2382 } 2986 2383 2987 2384 static void __init set_ftrace_early_filters(void) 2988 2385 { 2989 2386 if (ftrace_filter_buf[0]) 2990 - set_ftrace_early_filter(ftrace_filter_buf, 1); 2387 + set_ftrace_early_filter(&global_ops, ftrace_filter_buf, 1); 2991 2388 if (ftrace_notrace_buf[0]) 2992 - set_ftrace_early_filter(ftrace_notrace_buf, 0); 2389 + set_ftrace_early_filter(&global_ops, ftrace_notrace_buf, 0); 2993 2390 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 2994 2391 if (ftrace_graph_buf[0]) 2995 2392 set_ftrace_early_graph(ftrace_graph_buf); ··· 2998 2393 } 2999 2394 3000 2395 static int 3001 - ftrace_regex_release(struct inode *inode, struct file *file, int enable) 2396 + ftrace_regex_release(struct inode *inode, struct file *file) 3002 2397 { 3003 2398 struct seq_file *m = (struct seq_file *)file->private_data; 3004 2399 struct ftrace_iterator *iter; 2400 + struct ftrace_hash **orig_hash; 3005 2401 struct trace_parser *parser; 2402 + int filter_hash; 2403 + int ret; 3006 2404 3007 2405 mutex_lock(&ftrace_regex_lock); 3008 2406 if (file->f_mode & FMODE_READ) { ··· 3018 2410 parser = &iter->parser; 3019 2411 if (trace_parser_loaded(parser)) { 3020 2412 parser->buffer[parser->idx] = 0; 3021 - ftrace_match_records(parser->buffer, parser->idx, enable); 2413 + ftrace_match_records(iter->hash, parser->buffer, parser->idx); 3022 2414 } 3023 2415 3024 - mutex_lock(&ftrace_lock); 3025 - if (ftrace_start_up && ftrace_enabled) 3026 - ftrace_run_update_code(FTRACE_ENABLE_CALLS); 3027 - mutex_unlock(&ftrace_lock); 3028 - 3029 2416 trace_parser_put(parser); 2417 + 2418 + if (file->f_mode & FMODE_WRITE) { 2419 + filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); 2420 + 2421 + if (filter_hash) 2422 + orig_hash = &iter->ops->filter_hash; 2423 + else 2424 + orig_hash = &iter->ops->notrace_hash; 2425 + 2426 + mutex_lock(&ftrace_lock); 2427 + /* 2428 + * Remove the current set, update the hash and add 2429 + * them back. 2430 + */ 2431 + ftrace_hash_rec_disable(iter->ops, filter_hash); 2432 + ret = ftrace_hash_move(orig_hash, iter->hash); 2433 + if (!ret) { 2434 + ftrace_hash_rec_enable(iter->ops, filter_hash); 2435 + if (iter->ops->flags & FTRACE_OPS_FL_ENABLED 2436 + && ftrace_enabled) 2437 + ftrace_run_update_code(FTRACE_ENABLE_CALLS); 2438 + } 2439 + mutex_unlock(&ftrace_lock); 2440 + } 2441 + free_ftrace_hash(iter->hash); 3030 2442 kfree(iter); 3031 2443 3032 2444 mutex_unlock(&ftrace_regex_lock); 3033 2445 return 0; 3034 - } 3035 - 3036 - static int 3037 - ftrace_filter_release(struct inode *inode, struct file *file) 3038 - { 3039 - return ftrace_regex_release(inode, file, 1); 3040 - } 3041 - 3042 - static int 3043 - ftrace_notrace_release(struct inode *inode, struct file *file) 3044 - { 3045 - return ftrace_regex_release(inode, file, 0); 3046 2446 } 3047 2447 3048 2448 static const struct file_operations ftrace_avail_fops = { ··· 3060 2444 .release = seq_release_private, 3061 2445 }; 3062 2446 3063 - static const struct file_operations ftrace_failures_fops = { 3064 - .open = ftrace_failures_open, 2447 + static const struct file_operations ftrace_enabled_fops = { 2448 + .open = ftrace_enabled_open, 3065 2449 .read = seq_read, 3066 2450 .llseek = seq_lseek, 3067 2451 .release = seq_release_private, ··· 3072 2456 .read = seq_read, 3073 2457 .write = ftrace_filter_write, 3074 2458 .llseek = ftrace_regex_lseek, 3075 - .release = ftrace_filter_release, 2459 + .release = ftrace_regex_release, 3076 2460 }; 3077 2461 3078 2462 static const struct file_operations ftrace_notrace_fops = { ··· 3080 2464 .read = seq_read, 3081 2465 .write = ftrace_notrace_write, 3082 2466 .llseek = ftrace_regex_lseek, 3083 - .release = ftrace_notrace_release, 2467 + .release = ftrace_regex_release, 3084 2468 }; 3085 2469 3086 2470 #ifdef CONFIG_FUNCTION_GRAPH_TRACER ··· 3189 2573 bool exists; 3190 2574 int i; 3191 2575 3192 - if (ftrace_disabled) 3193 - return -ENODEV; 3194 - 3195 2576 /* decode regex */ 3196 2577 type = filter_parse_regex(buffer, strlen(buffer), &search, &not); 3197 2578 if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) ··· 3197 2584 search_len = strlen(search); 3198 2585 3199 2586 mutex_lock(&ftrace_lock); 2587 + 2588 + if (unlikely(ftrace_disabled)) { 2589 + mutex_unlock(&ftrace_lock); 2590 + return -ENODEV; 2591 + } 2592 + 3200 2593 do_for_each_ftrace_rec(pg, rec) { 3201 2594 3202 - if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) 2595 + if (rec->flags & FTRACE_FL_FREE) 3203 2596 continue; 3204 2597 3205 - if (ftrace_match_record(rec, search, search_len, type)) { 2598 + if (ftrace_match_record(rec, NULL, search, search_len, type)) { 3206 2599 /* if it is in the array */ 3207 2600 exists = false; 3208 2601 for (i = 0; i < *idx; i++) { ··· 3298 2679 trace_create_file("available_filter_functions", 0444, 3299 2680 d_tracer, NULL, &ftrace_avail_fops); 3300 2681 3301 - trace_create_file("failures", 0444, 3302 - d_tracer, NULL, &ftrace_failures_fops); 2682 + trace_create_file("enabled_functions", 0444, 2683 + d_tracer, NULL, &ftrace_enabled_fops); 3303 2684 3304 2685 trace_create_file("set_ftrace_filter", 0644, d_tracer, 3305 2686 NULL, &ftrace_filter_fops); ··· 3322 2703 { 3323 2704 unsigned long *p; 3324 2705 unsigned long addr; 3325 - unsigned long flags; 3326 2706 3327 2707 mutex_lock(&ftrace_lock); 3328 2708 p = start; ··· 3338 2720 ftrace_record_ip(addr); 3339 2721 } 3340 2722 3341 - /* disable interrupts to prevent kstop machine */ 3342 - local_irq_save(flags); 3343 2723 ftrace_update_code(mod); 3344 - local_irq_restore(flags); 3345 2724 mutex_unlock(&ftrace_lock); 3346 2725 3347 2726 return 0; ··· 3350 2735 struct dyn_ftrace *rec; 3351 2736 struct ftrace_page *pg; 3352 2737 3353 - if (ftrace_disabled) 3354 - return; 3355 - 3356 2738 mutex_lock(&ftrace_lock); 2739 + 2740 + if (ftrace_disabled) 2741 + goto out_unlock; 2742 + 3357 2743 do_for_each_ftrace_rec(pg, rec) { 3358 2744 if (within_module_core(rec->ip, mod)) { 3359 2745 /* ··· 3365 2749 ftrace_free_rec(rec); 3366 2750 } 3367 2751 } while_for_each_ftrace_rec(); 2752 + out_unlock: 3368 2753 mutex_unlock(&ftrace_lock); 3369 2754 } 3370 2755 ··· 3452 2835 3453 2836 #else 3454 2837 2838 + static struct ftrace_ops global_ops = { 2839 + .func = ftrace_stub, 2840 + }; 2841 + 3455 2842 static int __init ftrace_nodyn_init(void) 3456 2843 { 3457 2844 ftrace_enabled = 1; ··· 3466 2845 static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } 3467 2846 static inline void ftrace_startup_enable(int command) { } 3468 2847 /* Keep as macros so we do not need to define the commands */ 3469 - # define ftrace_startup(command) do { } while (0) 3470 - # define ftrace_shutdown(command) do { } while (0) 2848 + # define ftrace_startup(ops, command) do { } while (0) 2849 + # define ftrace_shutdown(ops, command) do { } while (0) 3471 2850 # define ftrace_startup_sysctl() do { } while (0) 3472 2851 # define ftrace_shutdown_sysctl() do { } while (0) 2852 + 2853 + static inline int 2854 + ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) 2855 + { 2856 + return 1; 2857 + } 2858 + 3473 2859 #endif /* CONFIG_DYNAMIC_FTRACE */ 2860 + 2861 + static void 2862 + ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip) 2863 + { 2864 + struct ftrace_ops *op; 2865 + 2866 + /* 2867 + * Some of the ops may be dynamically allocated, 2868 + * they must be freed after a synchronize_sched(). 2869 + */ 2870 + preempt_disable_notrace(); 2871 + op = rcu_dereference_raw(ftrace_ops_list); 2872 + while (op != &ftrace_list_end) { 2873 + if (ftrace_ops_test(op, ip)) 2874 + op->func(ip, parent_ip); 2875 + op = rcu_dereference_raw(op->next); 2876 + }; 2877 + preempt_enable_notrace(); 2878 + } 3474 2879 3475 2880 static void clear_ftrace_swapper(void) 3476 2881 { ··· 3790 3143 */ 3791 3144 int register_ftrace_function(struct ftrace_ops *ops) 3792 3145 { 3793 - int ret; 3794 - 3795 - if (unlikely(ftrace_disabled)) 3796 - return -1; 3146 + int ret = -1; 3797 3147 3798 3148 mutex_lock(&ftrace_lock); 3799 3149 3800 - ret = __register_ftrace_function(ops); 3801 - ftrace_startup(0); 3150 + if (unlikely(ftrace_disabled)) 3151 + goto out_unlock; 3802 3152 3153 + ret = __register_ftrace_function(ops); 3154 + if (!ret) 3155 + ftrace_startup(ops, 0); 3156 + 3157 + 3158 + out_unlock: 3803 3159 mutex_unlock(&ftrace_lock); 3804 3160 return ret; 3805 3161 } 3162 + EXPORT_SYMBOL_GPL(register_ftrace_function); 3806 3163 3807 3164 /** 3808 3165 * unregister_ftrace_function - unregister a function for profiling. ··· 3820 3169 3821 3170 mutex_lock(&ftrace_lock); 3822 3171 ret = __unregister_ftrace_function(ops); 3823 - ftrace_shutdown(0); 3172 + if (!ret) 3173 + ftrace_shutdown(ops, 0); 3824 3174 mutex_unlock(&ftrace_lock); 3825 3175 3826 3176 return ret; 3827 3177 } 3178 + EXPORT_SYMBOL_GPL(unregister_ftrace_function); 3828 3179 3829 3180 int 3830 3181 ftrace_enable_sysctl(struct ctl_table *table, int write, 3831 3182 void __user *buffer, size_t *lenp, 3832 3183 loff_t *ppos) 3833 3184 { 3834 - int ret; 3835 - 3836 - if (unlikely(ftrace_disabled)) 3837 - return -ENODEV; 3185 + int ret = -ENODEV; 3838 3186 3839 3187 mutex_lock(&ftrace_lock); 3840 3188 3841 - ret = proc_dointvec(table, write, buffer, lenp, ppos); 3189 + if (unlikely(ftrace_disabled)) 3190 + goto out; 3191 + 3192 + ret = proc_dointvec(table, write, buffer, lenp, ppos); 3842 3193 3843 3194 if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) 3844 3195 goto out; ··· 3852 3199 ftrace_startup_sysctl(); 3853 3200 3854 3201 /* we are starting ftrace again */ 3855 - if (ftrace_list != &ftrace_list_end) { 3856 - if (ftrace_list->next == &ftrace_list_end) 3857 - ftrace_trace_function = ftrace_list->func; 3202 + if (ftrace_ops_list != &ftrace_list_end) { 3203 + if (ftrace_ops_list->next == &ftrace_list_end) 3204 + ftrace_trace_function = ftrace_ops_list->func; 3858 3205 else 3859 - ftrace_trace_function = ftrace_list_func; 3206 + ftrace_trace_function = ftrace_ops_list_func; 3860 3207 } 3861 3208 3862 3209 } else { ··· 4045 3392 ftrace_graph_return = retfunc; 4046 3393 ftrace_graph_entry = entryfunc; 4047 3394 4048 - ftrace_startup(FTRACE_START_FUNC_RET); 3395 + ftrace_startup(&global_ops, FTRACE_START_FUNC_RET); 4049 3396 4050 3397 out: 4051 3398 mutex_unlock(&ftrace_lock); ··· 4062 3409 ftrace_graph_active--; 4063 3410 ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; 4064 3411 ftrace_graph_entry = ftrace_graph_entry_stub; 4065 - ftrace_shutdown(FTRACE_STOP_FUNC_RET); 3412 + ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET); 4066 3413 unregister_pm_notifier(&ftrace_suspend_notifier); 4067 3414 unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); 4068 3415
+12 -3
kernel/trace/trace.c
··· 2014 2014 { 2015 2015 enum print_line_t ret; 2016 2016 2017 - if (iter->lost_events) 2018 - trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 2019 - iter->cpu, iter->lost_events); 2017 + if (iter->lost_events && 2018 + !trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 2019 + iter->cpu, iter->lost_events)) 2020 + return TRACE_TYPE_PARTIAL_LINE; 2020 2021 2021 2022 if (iter->trace && iter->trace->print_line) { 2022 2023 ret = iter->trace->print_line(iter); ··· 3231 3230 3232 3231 if (iter->seq.len >= cnt) 3233 3232 break; 3233 + 3234 + /* 3235 + * Setting the full flag means we reached the trace_seq buffer 3236 + * size and we should leave by partial output condition above. 3237 + * One of the trace_seq_* functions is not used properly. 3238 + */ 3239 + WARN_ONCE(iter->seq.full, "full flag set for trace type %d", 3240 + iter->ent->type); 3234 3241 } 3235 3242 trace_access_unlock(iter->cpu_file); 3236 3243 trace_event_read_unlock();
+2
kernel/trace/trace.h
··· 419 419 extern unsigned long ftrace_update_tot_cnt; 420 420 #define DYN_FTRACE_TEST_NAME trace_selftest_dynamic_test_func 421 421 extern int DYN_FTRACE_TEST_NAME(void); 422 + #define DYN_FTRACE_TEST_NAME2 trace_selftest_dynamic_test_func2 423 + extern int DYN_FTRACE_TEST_NAME2(void); 422 424 #endif 423 425 424 426 extern int ring_buffer_expanded;
+2
kernel/trace/trace_functions.c
··· 149 149 static struct ftrace_ops trace_ops __read_mostly = 150 150 { 151 151 .func = function_trace_call, 152 + .flags = FTRACE_OPS_FL_GLOBAL, 152 153 }; 153 154 154 155 static struct ftrace_ops trace_stack_ops __read_mostly = 155 156 { 156 157 .func = function_stack_trace_call, 158 + .flags = FTRACE_OPS_FL_GLOBAL, 157 159 }; 158 160 159 161 /* Our two options */
+1
kernel/trace/trace_irqsoff.c
··· 153 153 static struct ftrace_ops trace_ops __read_mostly = 154 154 { 155 155 .func = irqsoff_tracer_call, 156 + .flags = FTRACE_OPS_FL_GLOBAL, 156 157 }; 157 158 #endif /* CONFIG_FUNCTION_TRACER */ 158 159
+3
kernel/trace/trace_output.c
··· 830 830 enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags, 831 831 struct trace_event *event) 832 832 { 833 + if (!trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type)) 834 + return TRACE_TYPE_PARTIAL_LINE; 835 + 833 836 return TRACE_TYPE_HANDLED; 834 837 } 835 838
+108 -12
kernel/trace/trace_printk.c
··· 32 32 33 33 struct trace_bprintk_fmt { 34 34 struct list_head list; 35 - char fmt[0]; 35 + const char *fmt; 36 36 }; 37 37 38 38 static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) ··· 49 49 void hold_module_trace_bprintk_format(const char **start, const char **end) 50 50 { 51 51 const char **iter; 52 + char *fmt; 52 53 53 54 mutex_lock(&btrace_mutex); 54 55 for (iter = start; iter < end; iter++) { ··· 59 58 continue; 60 59 } 61 60 62 - tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt) 63 - + strlen(*iter) + 1, GFP_KERNEL); 64 - if (tb_fmt) { 61 + tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL); 62 + if (tb_fmt) 63 + fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL); 64 + if (tb_fmt && fmt) { 65 65 list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); 66 - strcpy(tb_fmt->fmt, *iter); 66 + strcpy(fmt, *iter); 67 + tb_fmt->fmt = fmt; 67 68 *iter = tb_fmt->fmt; 68 - } else 69 + } else { 70 + kfree(tb_fmt); 69 71 *iter = NULL; 72 + } 70 73 } 71 74 mutex_unlock(&btrace_mutex); 72 75 } ··· 89 84 return 0; 90 85 } 91 86 87 + /* 88 + * The debugfs/tracing/printk_formats file maps the addresses with 89 + * the ASCII formats that are used in the bprintk events in the 90 + * buffer. For userspace tools to be able to decode the events from 91 + * the buffer, they need to be able to map the address with the format. 92 + * 93 + * The addresses of the bprintk formats are in their own section 94 + * __trace_printk_fmt. But for modules we copy them into a link list. 95 + * The code to print the formats and their addresses passes around the 96 + * address of the fmt string. If the fmt address passed into the seq 97 + * functions is within the kernel core __trace_printk_fmt section, then 98 + * it simply uses the next pointer in the list. 99 + * 100 + * When the fmt pointer is outside the kernel core __trace_printk_fmt 101 + * section, then we need to read the link list pointers. The trick is 102 + * we pass the address of the string to the seq function just like 103 + * we do for the kernel core formats. To get back the structure that 104 + * holds the format, we simply use containerof() and then go to the 105 + * next format in the list. 106 + */ 107 + static const char ** 108 + find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos) 109 + { 110 + struct trace_bprintk_fmt *mod_fmt; 111 + 112 + if (list_empty(&trace_bprintk_fmt_list)) 113 + return NULL; 114 + 115 + /* 116 + * v will point to the address of the fmt record from t_next 117 + * v will be NULL from t_start. 118 + * If this is the first pointer or called from start 119 + * then we need to walk the list. 120 + */ 121 + if (!v || start_index == *pos) { 122 + struct trace_bprintk_fmt *p; 123 + 124 + /* search the module list */ 125 + list_for_each_entry(p, &trace_bprintk_fmt_list, list) { 126 + if (start_index == *pos) 127 + return &p->fmt; 128 + start_index++; 129 + } 130 + /* pos > index */ 131 + return NULL; 132 + } 133 + 134 + /* 135 + * v points to the address of the fmt field in the mod list 136 + * structure that holds the module print format. 137 + */ 138 + mod_fmt = container_of(v, typeof(*mod_fmt), fmt); 139 + if (mod_fmt->list.next == &trace_bprintk_fmt_list) 140 + return NULL; 141 + 142 + mod_fmt = container_of(mod_fmt->list.next, typeof(*mod_fmt), list); 143 + 144 + return &mod_fmt->fmt; 145 + } 146 + 147 + static void format_mod_start(void) 148 + { 149 + mutex_lock(&btrace_mutex); 150 + } 151 + 152 + static void format_mod_stop(void) 153 + { 154 + mutex_unlock(&btrace_mutex); 155 + } 156 + 92 157 #else /* !CONFIG_MODULES */ 93 158 __init static int 94 159 module_trace_bprintk_format_notify(struct notifier_block *self, ··· 166 91 { 167 92 return 0; 168 93 } 94 + static inline const char ** 95 + find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos) 96 + { 97 + return NULL; 98 + } 99 + static inline void format_mod_start(void) { } 100 + static inline void format_mod_stop(void) { } 169 101 #endif /* CONFIG_MODULES */ 170 102 171 103 ··· 235 153 } 236 154 EXPORT_SYMBOL_GPL(__ftrace_vprintk); 237 155 156 + static const char **find_next(void *v, loff_t *pos) 157 + { 158 + const char **fmt = v; 159 + int start_index; 160 + 161 + if (!fmt) 162 + fmt = __start___trace_bprintk_fmt + *pos; 163 + 164 + start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt; 165 + 166 + if (*pos < start_index) 167 + return fmt; 168 + 169 + return find_next_mod_format(start_index, v, fmt, pos); 170 + } 171 + 238 172 static void * 239 173 t_start(struct seq_file *m, loff_t *pos) 240 174 { 241 - const char **fmt = __start___trace_bprintk_fmt + *pos; 242 - 243 - if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) 244 - return NULL; 245 - return fmt; 175 + format_mod_start(); 176 + return find_next(NULL, pos); 246 177 } 247 178 248 179 static void *t_next(struct seq_file *m, void * v, loff_t *pos) 249 180 { 250 181 (*pos)++; 251 - return t_start(m, pos); 182 + return find_next(v, pos); 252 183 } 253 184 254 185 static int t_show(struct seq_file *m, void *v) ··· 300 205 301 206 static void t_stop(struct seq_file *m, void *p) 302 207 { 208 + format_mod_stop(); 303 209 } 304 210 305 211 static const struct seq_operations show_format_seq_ops = {
+1
kernel/trace/trace_sched_wakeup.c
··· 129 129 static struct ftrace_ops trace_ops __read_mostly = 130 130 { 131 131 .func = wakeup_tracer_call, 132 + .flags = FTRACE_OPS_FL_GLOBAL, 132 133 }; 133 134 #endif /* CONFIG_FUNCTION_TRACER */ 134 135
+211 -3
kernel/trace/trace_selftest.c
··· 101 101 102 102 #ifdef CONFIG_DYNAMIC_FTRACE 103 103 104 + static int trace_selftest_test_probe1_cnt; 105 + static void trace_selftest_test_probe1_func(unsigned long ip, 106 + unsigned long pip) 107 + { 108 + trace_selftest_test_probe1_cnt++; 109 + } 110 + 111 + static int trace_selftest_test_probe2_cnt; 112 + static void trace_selftest_test_probe2_func(unsigned long ip, 113 + unsigned long pip) 114 + { 115 + trace_selftest_test_probe2_cnt++; 116 + } 117 + 118 + static int trace_selftest_test_probe3_cnt; 119 + static void trace_selftest_test_probe3_func(unsigned long ip, 120 + unsigned long pip) 121 + { 122 + trace_selftest_test_probe3_cnt++; 123 + } 124 + 125 + static int trace_selftest_test_global_cnt; 126 + static void trace_selftest_test_global_func(unsigned long ip, 127 + unsigned long pip) 128 + { 129 + trace_selftest_test_global_cnt++; 130 + } 131 + 132 + static int trace_selftest_test_dyn_cnt; 133 + static void trace_selftest_test_dyn_func(unsigned long ip, 134 + unsigned long pip) 135 + { 136 + trace_selftest_test_dyn_cnt++; 137 + } 138 + 139 + static struct ftrace_ops test_probe1 = { 140 + .func = trace_selftest_test_probe1_func, 141 + }; 142 + 143 + static struct ftrace_ops test_probe2 = { 144 + .func = trace_selftest_test_probe2_func, 145 + }; 146 + 147 + static struct ftrace_ops test_probe3 = { 148 + .func = trace_selftest_test_probe3_func, 149 + }; 150 + 151 + static struct ftrace_ops test_global = { 152 + .func = trace_selftest_test_global_func, 153 + .flags = FTRACE_OPS_FL_GLOBAL, 154 + }; 155 + 156 + static void print_counts(void) 157 + { 158 + printk("(%d %d %d %d %d) ", 159 + trace_selftest_test_probe1_cnt, 160 + trace_selftest_test_probe2_cnt, 161 + trace_selftest_test_probe3_cnt, 162 + trace_selftest_test_global_cnt, 163 + trace_selftest_test_dyn_cnt); 164 + } 165 + 166 + static void reset_counts(void) 167 + { 168 + trace_selftest_test_probe1_cnt = 0; 169 + trace_selftest_test_probe2_cnt = 0; 170 + trace_selftest_test_probe3_cnt = 0; 171 + trace_selftest_test_global_cnt = 0; 172 + trace_selftest_test_dyn_cnt = 0; 173 + } 174 + 175 + static int trace_selftest_ops(int cnt) 176 + { 177 + int save_ftrace_enabled = ftrace_enabled; 178 + struct ftrace_ops *dyn_ops; 179 + char *func1_name; 180 + char *func2_name; 181 + int len1; 182 + int len2; 183 + int ret = -1; 184 + 185 + printk(KERN_CONT "PASSED\n"); 186 + pr_info("Testing dynamic ftrace ops #%d: ", cnt); 187 + 188 + ftrace_enabled = 1; 189 + reset_counts(); 190 + 191 + /* Handle PPC64 '.' name */ 192 + func1_name = "*" __stringify(DYN_FTRACE_TEST_NAME); 193 + func2_name = "*" __stringify(DYN_FTRACE_TEST_NAME2); 194 + len1 = strlen(func1_name); 195 + len2 = strlen(func2_name); 196 + 197 + /* 198 + * Probe 1 will trace function 1. 199 + * Probe 2 will trace function 2. 200 + * Probe 3 will trace functions 1 and 2. 201 + */ 202 + ftrace_set_filter(&test_probe1, func1_name, len1, 1); 203 + ftrace_set_filter(&test_probe2, func2_name, len2, 1); 204 + ftrace_set_filter(&test_probe3, func1_name, len1, 1); 205 + ftrace_set_filter(&test_probe3, func2_name, len2, 0); 206 + 207 + register_ftrace_function(&test_probe1); 208 + register_ftrace_function(&test_probe2); 209 + register_ftrace_function(&test_probe3); 210 + register_ftrace_function(&test_global); 211 + 212 + DYN_FTRACE_TEST_NAME(); 213 + 214 + print_counts(); 215 + 216 + if (trace_selftest_test_probe1_cnt != 1) 217 + goto out; 218 + if (trace_selftest_test_probe2_cnt != 0) 219 + goto out; 220 + if (trace_selftest_test_probe3_cnt != 1) 221 + goto out; 222 + if (trace_selftest_test_global_cnt == 0) 223 + goto out; 224 + 225 + DYN_FTRACE_TEST_NAME2(); 226 + 227 + print_counts(); 228 + 229 + if (trace_selftest_test_probe1_cnt != 1) 230 + goto out; 231 + if (trace_selftest_test_probe2_cnt != 1) 232 + goto out; 233 + if (trace_selftest_test_probe3_cnt != 2) 234 + goto out; 235 + 236 + /* Add a dynamic probe */ 237 + dyn_ops = kzalloc(sizeof(*dyn_ops), GFP_KERNEL); 238 + if (!dyn_ops) { 239 + printk("MEMORY ERROR "); 240 + goto out; 241 + } 242 + 243 + dyn_ops->func = trace_selftest_test_dyn_func; 244 + 245 + register_ftrace_function(dyn_ops); 246 + 247 + trace_selftest_test_global_cnt = 0; 248 + 249 + DYN_FTRACE_TEST_NAME(); 250 + 251 + print_counts(); 252 + 253 + if (trace_selftest_test_probe1_cnt != 2) 254 + goto out_free; 255 + if (trace_selftest_test_probe2_cnt != 1) 256 + goto out_free; 257 + if (trace_selftest_test_probe3_cnt != 3) 258 + goto out_free; 259 + if (trace_selftest_test_global_cnt == 0) 260 + goto out; 261 + if (trace_selftest_test_dyn_cnt == 0) 262 + goto out_free; 263 + 264 + DYN_FTRACE_TEST_NAME2(); 265 + 266 + print_counts(); 267 + 268 + if (trace_selftest_test_probe1_cnt != 2) 269 + goto out_free; 270 + if (trace_selftest_test_probe2_cnt != 2) 271 + goto out_free; 272 + if (trace_selftest_test_probe3_cnt != 4) 273 + goto out_free; 274 + 275 + ret = 0; 276 + out_free: 277 + unregister_ftrace_function(dyn_ops); 278 + kfree(dyn_ops); 279 + 280 + out: 281 + /* Purposely unregister in the same order */ 282 + unregister_ftrace_function(&test_probe1); 283 + unregister_ftrace_function(&test_probe2); 284 + unregister_ftrace_function(&test_probe3); 285 + unregister_ftrace_function(&test_global); 286 + 287 + /* Make sure everything is off */ 288 + reset_counts(); 289 + DYN_FTRACE_TEST_NAME(); 290 + DYN_FTRACE_TEST_NAME(); 291 + 292 + if (trace_selftest_test_probe1_cnt || 293 + trace_selftest_test_probe2_cnt || 294 + trace_selftest_test_probe3_cnt || 295 + trace_selftest_test_global_cnt || 296 + trace_selftest_test_dyn_cnt) 297 + ret = -1; 298 + 299 + ftrace_enabled = save_ftrace_enabled; 300 + 301 + return ret; 302 + } 303 + 104 304 /* Test dynamic code modification and ftrace filters */ 105 305 int trace_selftest_startup_dynamic_tracing(struct tracer *trace, 106 306 struct trace_array *tr, ··· 331 131 func_name = "*" __stringify(DYN_FTRACE_TEST_NAME); 332 132 333 133 /* filter only on our function */ 334 - ftrace_set_filter(func_name, strlen(func_name), 1); 134 + ftrace_set_global_filter(func_name, strlen(func_name), 1); 335 135 336 136 /* enable tracing */ 337 137 ret = tracer_init(trace, tr); ··· 366 166 367 167 /* check the trace buffer */ 368 168 ret = trace_test_buffer(tr, &count); 369 - trace->reset(tr); 370 169 tracing_start(); 371 170 372 171 /* we should only have one item */ 373 172 if (!ret && count != 1) { 173 + trace->reset(tr); 374 174 printk(KERN_CONT ".. filter failed count=%ld ..", count); 375 175 ret = -1; 376 176 goto out; 377 177 } 178 + 179 + /* Test the ops with global tracing running */ 180 + ret = trace_selftest_ops(1); 181 + trace->reset(tr); 378 182 379 183 out: 380 184 ftrace_enabled = save_ftrace_enabled; 381 185 tracer_enabled = save_tracer_enabled; 382 186 383 187 /* Enable tracing on all functions again */ 384 - ftrace_set_filter(NULL, 0, 1); 188 + ftrace_set_global_filter(NULL, 0, 1); 189 + 190 + /* Test the ops with global tracing off */ 191 + if (!ret) 192 + ret = trace_selftest_ops(2); 385 193 386 194 return ret; 387 195 }
+6
kernel/trace/trace_selftest_dynamic.c
··· 5 5 /* used to call mcount */ 6 6 return 0; 7 7 } 8 + 9 + int DYN_FTRACE_TEST_NAME2(void) 10 + { 11 + /* used to call mcount */ 12 + return 0; 13 + }
+1
kernel/trace/trace_stack.c
··· 133 133 static struct ftrace_ops trace_ops __read_mostly = 134 134 { 135 135 .func = stack_trace_call, 136 + .flags = FTRACE_OPS_FL_GLOBAL, 136 137 }; 137 138 138 139 static ssize_t
+9 -14
kernel/tracepoint.c
··· 251 251 { 252 252 WARN_ON(strcmp((*entry)->name, elem->name) != 0); 253 253 254 - if (elem->regfunc && !elem->state && active) 254 + if (elem->regfunc && !jump_label_enabled(&elem->key) && active) 255 255 elem->regfunc(); 256 - else if (elem->unregfunc && elem->state && !active) 256 + else if (elem->unregfunc && jump_label_enabled(&elem->key) && !active) 257 257 elem->unregfunc(); 258 258 259 259 /* ··· 264 264 * is used. 265 265 */ 266 266 rcu_assign_pointer(elem->funcs, (*entry)->funcs); 267 - if (!elem->state && active) { 268 - jump_label_enable(&elem->state); 269 - elem->state = active; 270 - } else if (elem->state && !active) { 271 - jump_label_disable(&elem->state); 272 - elem->state = active; 273 - } 267 + if (active && !jump_label_enabled(&elem->key)) 268 + jump_label_inc(&elem->key); 269 + else if (!active && jump_label_enabled(&elem->key)) 270 + jump_label_dec(&elem->key); 274 271 } 275 272 276 273 /* ··· 278 281 */ 279 282 static void disable_tracepoint(struct tracepoint *elem) 280 283 { 281 - if (elem->unregfunc && elem->state) 284 + if (elem->unregfunc && jump_label_enabled(&elem->key)) 282 285 elem->unregfunc(); 283 286 284 - if (elem->state) { 285 - jump_label_disable(&elem->state); 286 - elem->state = 0; 287 - } 287 + if (jump_label_enabled(&elem->key)) 288 + jump_label_dec(&elem->key); 288 289 rcu_assign_pointer(elem->funcs, NULL); 289 290 } 290 291
+9 -3
scripts/Makefile.build
··· 244 244 245 245 ifdef CONFIG_FTRACE_MCOUNT_RECORD 246 246 ifdef BUILD_C_RECORDMCOUNT 247 + ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") 248 + RECORDMCOUNT_FLAGS = -w 249 + endif 247 250 # Due to recursion, we must skip empty.o. 248 251 # The empty.o file is created in the make process in order to determine 249 252 # the target endianness and word size. It is made before all other C 250 253 # files, including recordmcount. 251 254 sub_cmd_record_mcount = \ 252 255 if [ $(@) != "scripts/mod/empty.o" ]; then \ 253 - $(objtree)/scripts/recordmcount "$(@)"; \ 256 + $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ 254 257 fi; 258 + recordmcount_source := $(srctree)/scripts/recordmcount.c \ 259 + $(srctree)/scripts/recordmcount.h 255 260 else 256 261 sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ 257 262 "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ ··· 264 259 "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \ 265 260 "$(LD)" "$(NM)" "$(RM)" "$(MV)" \ 266 261 "$(if $(part-of-module),1,0)" "$(@)"; 262 + recordmcount_source := $(srctree)/scripts/recordmcount.pl 267 263 endif 268 264 cmd_record_mcount = \ 269 265 if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then \ ··· 285 279 endef 286 280 287 281 # Built-in and composite module parts 288 - $(obj)/%.o: $(src)/%.c FORCE 282 + $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE 289 283 $(call cmd,force_checksrc) 290 284 $(call if_changed_rule,cc_o_c) 291 285 292 286 # Single-part modules are special since we need to mark them in $(MODVERDIR) 293 287 294 - $(single-used-m): $(obj)/%.o: $(src)/%.c FORCE 288 + $(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE 295 289 $(call cmd,force_checksrc) 296 290 $(call if_changed_rule,cc_o_c) 297 291 @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
+114 -54
scripts/recordmcount.c
··· 24 24 #include <sys/types.h> 25 25 #include <sys/mman.h> 26 26 #include <sys/stat.h> 27 + #include <getopt.h> 27 28 #include <elf.h> 28 29 #include <fcntl.h> 29 30 #include <setjmp.h> ··· 40 39 static struct stat sb; /* Remember .st_size, etc. */ 41 40 static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ 42 41 static const char *altmcount; /* alternate mcount symbol name */ 42 + static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */ 43 43 44 44 /* setjmp() return values */ 45 45 enum { ··· 80 78 ulseek(int const fd, off_t const offset, int const whence) 81 79 { 82 80 off_t const w = lseek(fd, offset, whence); 83 - if ((off_t)-1 == w) { 81 + if (w == (off_t)-1) { 84 82 perror("lseek"); 85 83 fail_file(); 86 84 } ··· 113 111 umalloc(size_t size) 114 112 { 115 113 void *const addr = malloc(size); 116 - if (0 == addr) { 114 + if (addr == 0) { 117 115 fprintf(stderr, "malloc failed: %zu bytes\n", size); 118 116 fail_file(); 119 117 } 120 118 return addr; 119 + } 120 + 121 + static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 }; 122 + static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 }; 123 + static unsigned char *ideal_nop; 124 + 125 + static char rel_type_nop; 126 + 127 + static int (*make_nop)(void *map, size_t const offset); 128 + 129 + static int make_nop_x86(void *map, size_t const offset) 130 + { 131 + uint32_t *ptr; 132 + unsigned char *op; 133 + 134 + /* Confirm we have 0xe8 0x0 0x0 0x0 0x0 */ 135 + ptr = map + offset; 136 + if (*ptr != 0) 137 + return -1; 138 + 139 + op = map + offset - 1; 140 + if (*op != 0xe8) 141 + return -1; 142 + 143 + /* convert to nop */ 144 + ulseek(fd_map, offset - 1, SEEK_SET); 145 + uwrite(fd_map, ideal_nop, 5); 146 + return 0; 121 147 } 122 148 123 149 /* ··· 166 136 void *addr; 167 137 168 138 fd_map = open(fname, O_RDWR); 169 - if (0 > fd_map || 0 > fstat(fd_map, &sb)) { 139 + if (fd_map < 0 || fstat(fd_map, &sb) < 0) { 170 140 perror(fname); 171 141 fail_file(); 172 142 } ··· 177 147 addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, 178 148 fd_map, 0); 179 149 mmap_failed = 0; 180 - if (MAP_FAILED == addr) { 150 + if (addr == MAP_FAILED) { 181 151 mmap_failed = 1; 182 152 addr = umalloc(sb.st_size); 183 153 uread(fd_map, addr, sb.st_size); ··· 236 206 static int 237 207 is_mcounted_section_name(char const *const txtname) 238 208 { 239 - return 0 == strcmp(".text", txtname) || 240 - 0 == strcmp(".ref.text", txtname) || 241 - 0 == strcmp(".sched.text", txtname) || 242 - 0 == strcmp(".spinlock.text", txtname) || 243 - 0 == strcmp(".irqentry.text", txtname) || 244 - 0 == strcmp(".text.unlikely", txtname); 209 + return strcmp(".text", txtname) == 0 || 210 + strcmp(".ref.text", txtname) == 0 || 211 + strcmp(".sched.text", txtname) == 0 || 212 + strcmp(".spinlock.text", txtname) == 0 || 213 + strcmp(".irqentry.text", txtname) == 0 || 214 + strcmp(".kprobes.text", txtname) == 0 || 215 + strcmp(".text.unlikely", txtname) == 0; 245 216 } 246 217 247 218 /* 32 bit and 64 bit are very similar */ ··· 295 264 w8 = w8nat; 296 265 switch (ehdr->e_ident[EI_DATA]) { 297 266 static unsigned int const endian = 1; 298 - default: { 267 + default: 299 268 fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", 300 269 ehdr->e_ident[EI_DATA], fname); 301 270 fail_file(); 302 - } break; 303 - case ELFDATA2LSB: { 304 - if (1 != *(unsigned char const *)&endian) { 271 + break; 272 + case ELFDATA2LSB: 273 + if (*(unsigned char const *)&endian != 1) { 305 274 /* main() is big endian, file.o is little endian. */ 306 275 w = w4rev; 307 276 w2 = w2rev; 308 277 w8 = w8rev; 309 278 } 310 - } break; 311 - case ELFDATA2MSB: { 312 - if (0 != *(unsigned char const *)&endian) { 279 + break; 280 + case ELFDATA2MSB: 281 + if (*(unsigned char const *)&endian != 0) { 313 282 /* main() is little endian, file.o is big endian. */ 314 283 w = w4rev; 315 284 w2 = w2rev; 316 285 w8 = w8rev; 317 286 } 318 - } break; 287 + break; 319 288 } /* end switch */ 320 - if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG) 321 - || ET_REL != w2(ehdr->e_type) 322 - || EV_CURRENT != ehdr->e_ident[EI_VERSION]) { 289 + if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 290 + || w2(ehdr->e_type) != ET_REL 291 + || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { 323 292 fprintf(stderr, "unrecognized ET_REL file %s\n", fname); 324 293 fail_file(); 325 294 } 326 295 327 296 gpfx = 0; 328 297 switch (w2(ehdr->e_machine)) { 329 - default: { 298 + default: 330 299 fprintf(stderr, "unrecognized e_machine %d %s\n", 331 300 w2(ehdr->e_machine), fname); 332 301 fail_file(); 333 - } break; 334 - case EM_386: reltype = R_386_32; break; 302 + break; 303 + case EM_386: 304 + reltype = R_386_32; 305 + make_nop = make_nop_x86; 306 + ideal_nop = ideal_nop5_x86_32; 307 + mcount_adjust_32 = -1; 308 + break; 335 309 case EM_ARM: reltype = R_ARM_ABS32; 336 310 altmcount = "__gnu_mcount_nc"; 337 311 break; ··· 347 311 case EM_S390: /* reltype: e_class */ gpfx = '_'; break; 348 312 case EM_SH: reltype = R_SH_DIR32; break; 349 313 case EM_SPARCV9: reltype = R_SPARC_64; gpfx = '_'; break; 350 - case EM_X86_64: reltype = R_X86_64_64; break; 314 + case EM_X86_64: 315 + make_nop = make_nop_x86; 316 + ideal_nop = ideal_nop5_x86_64; 317 + reltype = R_X86_64_64; 318 + mcount_adjust_64 = -1; 319 + break; 351 320 } /* end switch */ 352 321 353 322 switch (ehdr->e_ident[EI_CLASS]) { 354 - default: { 323 + default: 355 324 fprintf(stderr, "unrecognized ELF class %d %s\n", 356 325 ehdr->e_ident[EI_CLASS], fname); 357 326 fail_file(); 358 - } break; 359 - case ELFCLASS32: { 360 - if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize) 361 - || sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) { 327 + break; 328 + case ELFCLASS32: 329 + if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr) 330 + || w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { 362 331 fprintf(stderr, 363 332 "unrecognized ET_REL file: %s\n", fname); 364 333 fail_file(); 365 334 } 366 - if (EM_S390 == w2(ehdr->e_machine)) 335 + if (w2(ehdr->e_machine) == EM_S390) { 367 336 reltype = R_390_32; 368 - if (EM_MIPS == w2(ehdr->e_machine)) { 337 + mcount_adjust_32 = -4; 338 + } 339 + if (w2(ehdr->e_machine) == EM_MIPS) { 369 340 reltype = R_MIPS_32; 370 341 is_fake_mcount32 = MIPS32_is_fake_mcount; 371 342 } 372 343 do32(ehdr, fname, reltype); 373 - } break; 344 + break; 374 345 case ELFCLASS64: { 375 346 Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; 376 - if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize) 377 - || sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) { 347 + if (w2(ghdr->e_ehsize) != sizeof(Elf64_Ehdr) 348 + || w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { 378 349 fprintf(stderr, 379 350 "unrecognized ET_REL file: %s\n", fname); 380 351 fail_file(); 381 352 } 382 - if (EM_S390 == w2(ghdr->e_machine)) 353 + if (w2(ghdr->e_machine) == EM_S390) { 383 354 reltype = R_390_64; 384 - if (EM_MIPS == w2(ghdr->e_machine)) { 355 + mcount_adjust_64 = -8; 356 + } 357 + if (w2(ghdr->e_machine) == EM_MIPS) { 385 358 reltype = R_MIPS_64; 386 359 Elf64_r_sym = MIPS64_r_sym; 387 360 Elf64_r_info = MIPS64_r_info; 388 361 is_fake_mcount64 = MIPS64_is_fake_mcount; 389 362 } 390 363 do64(ghdr, fname, reltype); 391 - } break; 364 + break; 365 + } 392 366 } /* end switch */ 393 367 394 368 cleanup(); 395 369 } 396 370 397 371 int 398 - main(int argc, char const *argv[]) 372 + main(int argc, char *argv[]) 399 373 { 400 374 const char ftrace[] = "/ftrace.o"; 401 375 int ftrace_size = sizeof(ftrace) - 1; 402 376 int n_error = 0; /* gcc-4.3.0 false positive complaint */ 377 + int c; 378 + int i; 403 379 404 - if (argc <= 1) { 405 - fprintf(stderr, "usage: recordmcount file.o...\n"); 380 + while ((c = getopt(argc, argv, "w")) >= 0) { 381 + switch (c) { 382 + case 'w': 383 + warn_on_notrace_sect = 1; 384 + break; 385 + default: 386 + fprintf(stderr, "usage: recordmcount [-w] file.o...\n"); 387 + return 0; 388 + } 389 + } 390 + 391 + if ((argc - optind) < 1) { 392 + fprintf(stderr, "usage: recordmcount [-w] file.o...\n"); 406 393 return 0; 407 394 } 408 395 409 396 /* Process each file in turn, allowing deep failure. */ 410 - for (--argc, ++argv; 0 < argc; --argc, ++argv) { 397 + for (i = optind; i < argc; i++) { 398 + char *file = argv[i]; 411 399 int const sjval = setjmp(jmpenv); 412 400 int len; 413 401 ··· 440 380 * function but does not call it. Since ftrace.o should 441 381 * not be traced anyway, we just skip it. 442 382 */ 443 - len = strlen(argv[0]); 383 + len = strlen(file); 444 384 if (len >= ftrace_size && 445 - strcmp(argv[0] + (len - ftrace_size), ftrace) == 0) 385 + strcmp(file + (len - ftrace_size), ftrace) == 0) 446 386 continue; 447 387 448 388 switch (sjval) { 449 - default: { 450 - fprintf(stderr, "internal error: %s\n", argv[0]); 389 + default: 390 + fprintf(stderr, "internal error: %s\n", file); 451 391 exit(1); 452 - } break; 453 - case SJ_SETJMP: { /* normal sequence */ 392 + break; 393 + case SJ_SETJMP: /* normal sequence */ 454 394 /* Avoid problems if early cleanup() */ 455 395 fd_map = -1; 456 396 ehdr_curr = NULL; 457 397 mmap_failed = 1; 458 - do_file(argv[0]); 459 - } break; 460 - case SJ_FAIL: { /* error in do_file or below */ 398 + do_file(file); 399 + break; 400 + case SJ_FAIL: /* error in do_file or below */ 461 401 ++n_error; 462 - } break; 463 - case SJ_SUCCEED: { /* premature success */ 402 + break; 403 + case SJ_SUCCEED: /* premature success */ 464 404 /* do nothing */ 465 - } break; 405 + break; 466 406 } /* end switch */ 467 407 } 468 408 return !!n_error;
+138 -36
scripts/recordmcount.h
··· 22 22 #undef is_fake_mcount 23 23 #undef fn_is_fake_mcount 24 24 #undef MIPS_is_fake_mcount 25 + #undef mcount_adjust 25 26 #undef sift_rel_mcount 27 + #undef nop_mcount 26 28 #undef find_secsym_ndx 27 29 #undef __has_rel_mcount 28 30 #undef has_rel_mcount 29 31 #undef tot_relsize 32 + #undef get_mcountsym 33 + #undef get_sym_str_and_relp 30 34 #undef do_func 31 35 #undef Elf_Addr 32 36 #undef Elf_Ehdr ··· 53 49 #ifdef RECORD_MCOUNT_64 54 50 # define append_func append64 55 51 # define sift_rel_mcount sift64_rel_mcount 52 + # define nop_mcount nop_mcount_64 56 53 # define find_secsym_ndx find64_secsym_ndx 57 54 # define __has_rel_mcount __has64_rel_mcount 58 55 # define has_rel_mcount has64_rel_mcount 59 56 # define tot_relsize tot64_relsize 57 + # define get_sym_str_and_relp get_sym_str_and_relp_64 60 58 # define do_func do64 59 + # define get_mcountsym get_mcountsym_64 61 60 # define is_fake_mcount is_fake_mcount64 62 61 # define fn_is_fake_mcount fn_is_fake_mcount64 63 62 # define MIPS_is_fake_mcount MIPS64_is_fake_mcount 63 + # define mcount_adjust mcount_adjust_64 64 64 # define Elf_Addr Elf64_Addr 65 65 # define Elf_Ehdr Elf64_Ehdr 66 66 # define Elf_Shdr Elf64_Shdr ··· 85 77 #else 86 78 # define append_func append32 87 79 # define sift_rel_mcount sift32_rel_mcount 80 + # define nop_mcount nop_mcount_32 88 81 # define find_secsym_ndx find32_secsym_ndx 89 82 # define __has_rel_mcount __has32_rel_mcount 90 83 # define has_rel_mcount has32_rel_mcount 91 84 # define tot_relsize tot32_relsize 85 + # define get_sym_str_and_relp get_sym_str_and_relp_32 92 86 # define do_func do32 87 + # define get_mcountsym get_mcountsym_32 93 88 # define is_fake_mcount is_fake_mcount32 94 89 # define fn_is_fake_mcount fn_is_fake_mcount32 95 90 # define MIPS_is_fake_mcount MIPS32_is_fake_mcount 91 + # define mcount_adjust mcount_adjust_32 96 92 # define Elf_Addr Elf32_Addr 97 93 # define Elf_Ehdr Elf32_Ehdr 98 94 # define Elf_Shdr Elf32_Shdr ··· 134 122 rp->r_info = _w(ELF_R_INFO(sym, type)); 135 123 } 136 124 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; 125 + 126 + static int mcount_adjust = 0; 137 127 138 128 /* 139 129 * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st ··· 248 234 uwrite(fd_map, ehdr, sizeof(*ehdr)); 249 235 } 250 236 237 + static unsigned get_mcountsym(Elf_Sym const *const sym0, 238 + Elf_Rel const *relp, 239 + char const *const str0) 240 + { 241 + unsigned mcountsym = 0; 242 + 243 + Elf_Sym const *const symp = 244 + &sym0[Elf_r_sym(relp)]; 245 + char const *symname = &str0[w(symp->st_name)]; 246 + char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; 247 + 248 + if (symname[0] == '.') 249 + ++symname; /* ppc64 hack */ 250 + if (strcmp(mcount, symname) == 0 || 251 + (altmcount && strcmp(altmcount, symname) == 0)) 252 + mcountsym = Elf_r_sym(relp); 253 + 254 + return mcountsym; 255 + } 256 + 257 + static void get_sym_str_and_relp(Elf_Shdr const *const relhdr, 258 + Elf_Ehdr const *const ehdr, 259 + Elf_Sym const **sym0, 260 + char const **str0, 261 + Elf_Rel const **relp) 262 + { 263 + Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 264 + + (void *)ehdr); 265 + unsigned const symsec_sh_link = w(relhdr->sh_link); 266 + Elf_Shdr const *const symsec = &shdr0[symsec_sh_link]; 267 + Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)]; 268 + Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset) 269 + + (void *)ehdr); 270 + 271 + *sym0 = (Elf_Sym const *)(_w(symsec->sh_offset) 272 + + (void *)ehdr); 273 + 274 + *str0 = (char const *)(_w(strsec->sh_offset) 275 + + (void *)ehdr); 276 + 277 + *relp = rel0; 278 + } 279 + 251 280 /* 252 281 * Look at the relocations in order to find the calls to mcount. 253 282 * Accumulate the section offsets that are found, and their relocation info, ··· 307 250 { 308 251 uint_t *const mloc0 = mlocp; 309 252 Elf_Rel *mrelp = *mrelpp; 310 - Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 311 - + (void *)ehdr); 312 - unsigned const symsec_sh_link = w(relhdr->sh_link); 313 - Elf_Shdr const *const symsec = &shdr0[symsec_sh_link]; 314 - Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset) 315 - + (void *)ehdr); 316 - 317 - Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)]; 318 - char const *const str0 = (char const *)(_w(strsec->sh_offset) 319 - + (void *)ehdr); 320 - 321 - Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset) 322 - + (void *)ehdr); 253 + Elf_Sym const *sym0; 254 + char const *str0; 255 + Elf_Rel const *relp; 323 256 unsigned rel_entsize = _w(relhdr->sh_entsize); 324 257 unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; 325 - Elf_Rel const *relp = rel0; 326 - 327 258 unsigned mcountsym = 0; 328 259 unsigned t; 329 260 330 - for (t = nrel; t; --t) { 331 - if (!mcountsym) { 332 - Elf_Sym const *const symp = 333 - &sym0[Elf_r_sym(relp)]; 334 - char const *symname = &str0[w(symp->st_name)]; 335 - char const *mcount = '_' == gpfx ? "_mcount" : "mcount"; 261 + get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); 336 262 337 - if ('.' == symname[0]) 338 - ++symname; /* ppc64 hack */ 339 - if (0 == strcmp(mcount, symname) || 340 - (altmcount && 0 == strcmp(altmcount, symname))) 341 - mcountsym = Elf_r_sym(relp); 342 - } 263 + for (t = nrel; t; --t) { 264 + if (!mcountsym) 265 + mcountsym = get_mcountsym(sym0, relp, str0); 343 266 344 267 if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { 345 - uint_t const addend = _w(_w(relp->r_offset) - recval); 346 - 268 + uint_t const addend = 269 + _w(_w(relp->r_offset) - recval + mcount_adjust); 347 270 mrelp->r_offset = _w(offbase 348 271 + ((void *)mlocp - (void *)mloc0)); 349 272 Elf_r_info(mrelp, recsym, reltype); 350 - if (sizeof(Elf_Rela) == rel_entsize) { 273 + if (rel_entsize == sizeof(Elf_Rela)) { 351 274 ((Elf_Rela *)mrelp)->r_addend = addend; 352 275 *mlocp++ = 0; 353 276 } else ··· 339 302 } 340 303 *mrelpp = mrelp; 341 304 return mlocp; 305 + } 306 + 307 + /* 308 + * Read the relocation table again, but this time its called on sections 309 + * that are not going to be traced. The mcount calls here will be converted 310 + * into nops. 311 + */ 312 + static void nop_mcount(Elf_Shdr const *const relhdr, 313 + Elf_Ehdr const *const ehdr, 314 + const char *const txtname) 315 + { 316 + Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 317 + + (void *)ehdr); 318 + Elf_Sym const *sym0; 319 + char const *str0; 320 + Elf_Rel const *relp; 321 + Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)]; 322 + unsigned rel_entsize = _w(relhdr->sh_entsize); 323 + unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; 324 + unsigned mcountsym = 0; 325 + unsigned t; 326 + int once = 0; 327 + 328 + get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); 329 + 330 + for (t = nrel; t; --t) { 331 + int ret = -1; 332 + 333 + if (!mcountsym) 334 + mcountsym = get_mcountsym(sym0, relp, str0); 335 + 336 + if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { 337 + if (make_nop) 338 + ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset); 339 + if (warn_on_notrace_sect && !once) { 340 + printf("Section %s has mcount callers being ignored\n", 341 + txtname); 342 + once = 1; 343 + /* just warn? */ 344 + if (!make_nop) 345 + return; 346 + } 347 + } 348 + 349 + /* 350 + * If we successfully removed the mcount, mark the relocation 351 + * as a nop (don't do anything with it). 352 + */ 353 + if (!ret) { 354 + Elf_Rel rel; 355 + rel = *(Elf_Rel *)relp; 356 + Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop); 357 + ulseek(fd_map, (void *)relp - (void *)ehdr, SEEK_SET); 358 + uwrite(fd_map, &rel, sizeof(rel)); 359 + } 360 + relp = (Elf_Rel const *)(rel_entsize + (void *)relp); 361 + } 342 362 } 343 363 344 364 ··· 448 354 Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)]; 449 355 char const *const txtname = &shstrtab[w(txthdr->sh_name)]; 450 356 451 - if (0 == strcmp("__mcount_loc", txtname)) { 357 + if (strcmp("__mcount_loc", txtname) == 0) { 452 358 fprintf(stderr, "warning: __mcount_loc already exists: %s\n", 453 359 fname); 454 360 succeed_file(); 455 361 } 456 - if (SHT_PROGBITS != w(txthdr->sh_type) || 457 - !is_mcounted_section_name(txtname)) 362 + if (w(txthdr->sh_type) != SHT_PROGBITS || 363 + !(w(txthdr->sh_flags) & SHF_EXECINSTR)) 458 364 return NULL; 459 365 return txtname; 460 366 } ··· 464 370 char const *const shstrtab, 465 371 char const *const fname) 466 372 { 467 - if (SHT_REL != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type)) 373 + if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA) 468 374 return NULL; 469 375 return __has_rel_mcount(relhdr, shdr0, shstrtab, fname); 470 376 } ··· 477 383 { 478 384 unsigned totrelsz = 0; 479 385 Elf_Shdr const *shdrp = shdr0; 386 + char const *txtname; 480 387 481 388 for (; nhdr; --nhdr, ++shdrp) { 482 - if (has_rel_mcount(shdrp, shdr0, shstrtab, fname)) 389 + txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname); 390 + if (txtname && is_mcounted_section_name(txtname)) 483 391 totrelsz += _w(shdrp->sh_size); 484 392 } 485 393 return totrelsz; ··· 517 421 for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { 518 422 char const *const txtname = has_rel_mcount(relhdr, shdr0, 519 423 shstrtab, fname); 520 - if (txtname) { 424 + if (txtname && is_mcounted_section_name(txtname)) { 521 425 uint_t recval = 0; 522 426 unsigned const recsym = find_secsym_ndx( 523 427 w(relhdr->sh_info), txtname, &recval, ··· 528 432 mlocp = sift_rel_mcount(mlocp, 529 433 (void *)mlocp - (void *)mloc0, &mrelp, 530 434 relhdr, ehdr, recsym, recval, reltype); 435 + } else if (txtname && (warn_on_notrace_sect || make_nop)) { 436 + /* 437 + * This section is ignored by ftrace, but still 438 + * has mcount calls. Convert them to nops now. 439 + */ 440 + nop_mcount(relhdr, ehdr, txtname); 531 441 } 532 442 } 533 443 if (mloc0 != mlocp) {
+5
scripts/recordmcount.pl
··· 134 134 ".sched.text" => 1, 135 135 ".spinlock.text" => 1, 136 136 ".irqentry.text" => 1, 137 + ".kprobes.text" => 1, 137 138 ".text.unlikely" => 1, 138 139 ); 139 140 ··· 223 222 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$"; 224 223 $type = ".quad"; 225 224 $alignment = 8; 225 + $mcount_adjust = -1; 226 226 227 227 # force flags for this arch 228 228 $ld .= " -m elf_x86_64"; ··· 233 231 234 232 } elsif ($arch eq "i386") { 235 233 $alignment = 4; 234 + $mcount_adjust = -1; 236 235 237 236 # force flags for this arch 238 237 $ld .= " -m elf_i386"; ··· 243 240 244 241 } elsif ($arch eq "s390" && $bits == 32) { 245 242 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_32\\s+_mcount\$"; 243 + $mcount_adjust = -4; 246 244 $alignment = 4; 247 245 $ld .= " -m elf_s390"; 248 246 $cc .= " -m31"; 249 247 250 248 } elsif ($arch eq "s390" && $bits == 64) { 251 249 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$"; 250 + $mcount_adjust = -8; 252 251 $alignment = 8; 253 252 $type = ".quad"; 254 253 $ld .= " -m elf64_s390";
+50 -2
tools/perf/Documentation/perf-script.txt
··· 113 113 Do various checks like samples ordering and lost events. 114 114 115 115 -f:: 116 - --fields 116 + --fields:: 117 117 Comma separated list of fields to print. Options are: 118 118 comm, tid, pid, time, cpu, event, trace, sym. Field 119 - list must be prepended with the type, trace, sw or hw, 119 + list can be prepended with the type, trace, sw or hw, 120 120 to indicate to which event type the field list applies. 121 121 e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace 122 + 123 + perf script -f <fields> 124 + 125 + is equivalent to: 126 + 127 + perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> 128 + 129 + i.e., the specified fields apply to all event types if the type string 130 + is not given. 131 + 132 + The arguments are processed in the order received. A later usage can 133 + reset a prior request. e.g.: 134 + 135 + -f trace: -f comm,tid,time,sym 136 + 137 + The first -f suppresses trace events (field list is ""), but then the 138 + second invocation sets the fields to comm,tid,time,sym. In this case a 139 + warning is given to the user: 140 + 141 + "Overriding previous field request for all events." 142 + 143 + Alternativey, consider the order: 144 + 145 + -f comm,tid,time,sym -f trace: 146 + 147 + The first -f sets the fields for all events and the second -f 148 + suppresses trace events. The user is given a warning message about 149 + the override, and the result of the above is that only S/W and H/W 150 + events are displayed with the given fields. 151 + 152 + For the 'wildcard' option if a user selected field is invalid for an 153 + event type, a message is displayed to the user that the option is 154 + ignored for that type. For example: 155 + 156 + $ perf script -f comm,tid,trace 157 + 'trace' not valid for hardware events. Ignoring. 158 + 'trace' not valid for software events. Ignoring. 159 + 160 + Alternatively, if the type is given an invalid field is specified it 161 + is an error. For example: 162 + 163 + perf script -v -f sw:comm,tid,trace 164 + 'trace' not valid for software events. 165 + 166 + At this point usage is displayed, and perf-script exits. 167 + 168 + Finally, a user may not set fields to none for all event types. 169 + i.e., -f "" is not allowed. 122 170 123 171 -k:: 124 172 --vmlinux=<file>::
+81 -26
tools/perf/Makefile
··· 5 5 # The default target of this Makefile is... 6 6 all: 7 7 8 + include config/utilities.mak 9 + 8 10 ifneq ($(OUTPUT),) 9 11 # check that the output directory actually exists 10 12 OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) ··· 14 12 endif 15 13 16 14 # Define V to have a more verbose compile. 15 + # 16 + # Define PYTHON to point to the python binary if the default 17 + # `python' is not correct; for example: PYTHON=python2 18 + # 19 + # Define PYTHON_CONFIG to point to the python-config binary if 20 + # the default `$(PYTHON)-config' is not correct. 17 21 # 18 22 # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 19 23 # ··· 142 134 # explicitly what architecture to check for. Fix this up for yours.. 143 135 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 144 136 145 - -include feature-tests.mak 137 + -include config/feature-tests.mak 146 138 147 139 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y) 148 140 CFLAGS := $(CFLAGS) -fstack-protector-all ··· 177 169 strip-libs = $(filter-out -l%,$(1)) 178 170 179 171 $(OUTPUT)python/perf.so: $(PYRF_OBJS) 180 - $(QUIET_GEN)( \ 181 - export CFLAGS="$(BASIC_CFLAGS)"; \ 182 - python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \ 183 - --build-temp='$(OUTPUT)python/temp' \ 184 - ) 185 - 172 + $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 173 + --quiet build_ext \ 174 + --build-lib='$(OUTPUT)python' \ 175 + --build-temp='$(OUTPUT)python/temp' 186 176 # 187 177 # No Perl scripts right now: 188 178 # ··· 485 479 endif 486 480 endif 487 481 488 - ifdef NO_LIBPYTHON 489 - BASIC_CFLAGS += -DNO_LIBPYTHON 482 + disable-python = $(eval $(disable-python_code)) 483 + define disable-python_code 484 + BASIC_CFLAGS += -DNO_LIBPYTHON 485 + $(if $(1),$(warning No $(1) was found)) 486 + $(warning Python support won't be built) 487 + endef 488 + 489 + override PYTHON := \ 490 + $(call get-executable-or-default,PYTHON,python) 491 + 492 + ifndef PYTHON 493 + $(call disable-python,python interpreter) 494 + python-clean := 490 495 else 491 - PYTHON_EMBED_LDOPTS = $(shell python-config --ldflags 2>/dev/null) 492 - PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 493 - PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) 494 - PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null` 495 - FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 496 - ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) 497 - msg := $(warning No Python.h found, install python-dev[el] to have python support in 'perf script' and to build the python bindings) 498 - BASIC_CFLAGS += -DNO_LIBPYTHON 499 - else 500 - ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 501 - EXTLIBS += $(PYTHON_EMBED_LIBADD) 502 - LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o 503 - LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o 504 - LANG_BINDINGS += $(OUTPUT)python/perf.so 505 - endif 496 + 497 + PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 498 + 499 + python-clean := $(PYTHON_WORD) util/setup.py clean \ 500 + --build-lib='$(OUTPUT)python' \ 501 + --build-temp='$(OUTPUT)python/temp' 502 + 503 + ifdef NO_LIBPYTHON 504 + $(call disable-python) 505 + else 506 + 507 + override PYTHON_CONFIG := \ 508 + $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config) 509 + 510 + ifndef PYTHON_CONFIG 511 + $(call disable-python,python-config tool) 512 + else 513 + 514 + PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) 515 + 516 + PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) 517 + PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 518 + PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) 519 + PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 520 + FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 521 + 522 + ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) 523 + $(call disable-python,Python.h (for Python 2.x)) 524 + else 525 + 526 + ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED)),y) 527 + $(warning Python 3 is not yet supported; please set) 528 + $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 529 + $(warning If you also have Python 2 installed, then) 530 + $(warning try something like:) 531 + $(warning $(and ,)) 532 + $(warning $(and ,) make PYTHON=python2) 533 + $(warning $(and ,)) 534 + $(warning Otherwise, disable Python support entirely:) 535 + $(warning $(and ,)) 536 + $(warning $(and ,) make NO_LIBPYTHON=1) 537 + $(warning $(and ,)) 538 + $(error $(and ,)) 539 + else 540 + ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 541 + EXTLIBS += $(PYTHON_EMBED_LIBADD) 542 + LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o 543 + LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o 544 + LANG_BINDINGS += $(OUTPUT)python/perf.so 545 + endif 546 + 547 + endif 548 + endif 549 + endif 506 550 endif 507 551 508 552 ifdef NO_DEMANGLE ··· 893 837 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 894 838 $(MAKE) -C Documentation/ clean 895 839 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS 896 - @python util/setup.py clean --build-lib='$(OUTPUT)python' \ 897 - --build-temp='$(OUTPUT)python/temp' 840 + $(python-clean) 898 841 899 842 .PHONY: all install clean strip 900 843 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
+231 -69
tools/perf/builtin-script.c
··· 49 49 }; 50 50 51 51 /* default set to maintain compatibility with current format */ 52 - static u64 output_fields[PERF_TYPE_MAX] = { 53 - [PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 54 - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 55 - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 52 + static struct { 53 + bool user_set; 54 + bool wildcard_set; 55 + u64 fields; 56 + u64 invalid_fields; 57 + } output[PERF_TYPE_MAX] = { 56 58 57 - [PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 58 - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 59 - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 59 + [PERF_TYPE_HARDWARE] = { 60 + .user_set = false, 60 61 61 - [PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \ 62 - PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \ 63 - PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, 62 + .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 63 + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 64 + PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 65 + 66 + .invalid_fields = PERF_OUTPUT_TRACE, 67 + }, 68 + 69 + [PERF_TYPE_SOFTWARE] = { 70 + .user_set = false, 71 + 72 + .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 73 + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 74 + PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 75 + 76 + .invalid_fields = PERF_OUTPUT_TRACE, 77 + }, 78 + 79 + [PERF_TYPE_TRACEPOINT] = { 80 + .user_set = false, 81 + 82 + .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 83 + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 84 + PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE, 85 + }, 86 + 87 + [PERF_TYPE_RAW] = { 88 + .user_set = false, 89 + 90 + .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 91 + PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 92 + PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 93 + 94 + .invalid_fields = PERF_OUTPUT_TRACE, 95 + }, 64 96 }; 65 97 66 - static bool output_set_by_user; 67 - 68 - #define PRINT_FIELD(x) (output_fields[attr->type] & PERF_OUTPUT_##x) 69 - 70 - static int perf_session__check_attr(struct perf_session *session, 71 - struct perf_event_attr *attr) 98 + static bool output_set_by_user(void) 72 99 { 100 + int j; 101 + for (j = 0; j < PERF_TYPE_MAX; ++j) { 102 + if (output[j].user_set) 103 + return true; 104 + } 105 + return false; 106 + } 107 + 108 + static const char *output_field2str(enum perf_output_field field) 109 + { 110 + int i, imax = ARRAY_SIZE(all_output_options); 111 + const char *str = ""; 112 + 113 + for (i = 0; i < imax; ++i) { 114 + if (all_output_options[i].field == field) { 115 + str = all_output_options[i].str; 116 + break; 117 + } 118 + } 119 + return str; 120 + } 121 + 122 + #define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 123 + 124 + static int perf_event_attr__check_stype(struct perf_event_attr *attr, 125 + u64 sample_type, const char *sample_msg, 126 + enum perf_output_field field) 127 + { 128 + int type = attr->type; 129 + const char *evname; 130 + 131 + if (attr->sample_type & sample_type) 132 + return 0; 133 + 134 + if (output[type].user_set) { 135 + evname = __event_name(attr->type, attr->config); 136 + pr_err("Samples for '%s' event do not have %s attribute set. " 137 + "Cannot print '%s' field.\n", 138 + evname, sample_msg, output_field2str(field)); 139 + return -1; 140 + } 141 + 142 + /* user did not ask for it explicitly so remove from the default list */ 143 + output[type].fields &= ~field; 144 + evname = __event_name(attr->type, attr->config); 145 + pr_debug("Samples for '%s' event do not have %s attribute set. " 146 + "Skipping '%s' field.\n", 147 + evname, sample_msg, output_field2str(field)); 148 + 149 + return 0; 150 + } 151 + 152 + static int perf_evsel__check_attr(struct perf_evsel *evsel, 153 + struct perf_session *session) 154 + { 155 + struct perf_event_attr *attr = &evsel->attr; 156 + 73 157 if (PRINT_FIELD(TRACE) && 74 158 !perf_session__has_traces(session, "record -R")) 75 159 return -EINVAL; 76 160 77 161 if (PRINT_FIELD(SYM)) { 78 - if (!(session->sample_type & PERF_SAMPLE_IP)) { 79 - pr_err("Samples do not contain IP data.\n"); 162 + if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", 163 + PERF_OUTPUT_SYM)) 80 164 return -EINVAL; 81 - } 165 + 82 166 if (!no_callchain && 83 - !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) 167 + !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) 84 168 symbol_conf.use_callchain = false; 85 169 } 86 170 87 171 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 88 - !(session->sample_type & PERF_SAMPLE_TID)) { 89 - pr_err("Samples do not contain TID/PID data.\n"); 172 + perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", 173 + PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 90 174 return -EINVAL; 91 - } 92 175 93 176 if (PRINT_FIELD(TIME) && 94 - !(session->sample_type & PERF_SAMPLE_TIME)) { 95 - pr_err("Samples do not contain timestamps.\n"); 177 + perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME", 178 + PERF_OUTPUT_TIME)) 96 179 return -EINVAL; 97 - } 98 180 99 181 if (PRINT_FIELD(CPU) && 100 - !(session->sample_type & PERF_SAMPLE_CPU)) { 101 - pr_err("Samples do not contain cpu.\n"); 182 + perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU", 183 + PERF_OUTPUT_CPU)) 102 184 return -EINVAL; 185 + 186 + return 0; 187 + } 188 + 189 + /* 190 + * verify all user requested events exist and the samples 191 + * have the expected data 192 + */ 193 + static int perf_session__check_output_opt(struct perf_session *session) 194 + { 195 + int j; 196 + struct perf_evsel *evsel; 197 + 198 + for (j = 0; j < PERF_TYPE_MAX; ++j) { 199 + evsel = perf_session__find_first_evtype(session, j); 200 + 201 + /* 202 + * even if fields is set to 0 (ie., show nothing) event must 203 + * exist if user explicitly includes it on the command line 204 + */ 205 + if (!evsel && output[j].user_set && !output[j].wildcard_set) { 206 + pr_err("%s events do not exist. " 207 + "Remove corresponding -f option to proceed.\n", 208 + event_type(j)); 209 + return -1; 210 + } 211 + 212 + if (evsel && output[j].fields && 213 + perf_evsel__check_attr(evsel, session)) 214 + return -1; 103 215 } 104 216 105 217 return 0; ··· 280 168 { 281 169 struct perf_event_attr *attr = &evsel->attr; 282 170 283 - if (output_fields[attr->type] == 0) 284 - return; 285 - 286 - if (perf_session__check_attr(session, attr) < 0) 171 + if (output[attr->type].fields == 0) 287 172 return; 288 173 289 174 print_sample_start(sample, thread, attr); ··· 560 451 { 561 452 char *tok; 562 453 int i, imax = sizeof(all_output_options) / sizeof(struct output_option); 454 + int j; 563 455 int rc = 0; 564 456 char *str = strdup(arg); 565 457 int type = -1; ··· 568 458 if (!str) 569 459 return -ENOMEM; 570 460 571 - tok = strtok(str, ":"); 572 - if (!tok) { 573 - fprintf(stderr, 574 - "Invalid field string - not prepended with type."); 575 - return -EINVAL; 576 - } 577 - 578 - /* first word should state which event type user 579 - * is specifying the fields 461 + /* first word can state for which event type the user is specifying 462 + * the fields. If no type exists, the specified fields apply to all 463 + * event types found in the file minus the invalid fields for a type. 580 464 */ 581 - if (!strcmp(tok, "hw")) 582 - type = PERF_TYPE_HARDWARE; 583 - else if (!strcmp(tok, "sw")) 584 - type = PERF_TYPE_SOFTWARE; 585 - else if (!strcmp(tok, "trace")) 586 - type = PERF_TYPE_TRACEPOINT; 587 - else { 588 - fprintf(stderr, "Invalid event type in field string."); 589 - return -EINVAL; 465 + tok = strchr(str, ':'); 466 + if (tok) { 467 + *tok = '\0'; 468 + tok++; 469 + if (!strcmp(str, "hw")) 470 + type = PERF_TYPE_HARDWARE; 471 + else if (!strcmp(str, "sw")) 472 + type = PERF_TYPE_SOFTWARE; 473 + else if (!strcmp(str, "trace")) 474 + type = PERF_TYPE_TRACEPOINT; 475 + else if (!strcmp(str, "raw")) 476 + type = PERF_TYPE_RAW; 477 + else { 478 + fprintf(stderr, "Invalid event type in field string.\n"); 479 + return -EINVAL; 480 + } 481 + 482 + if (output[type].user_set) 483 + pr_warning("Overriding previous field request for %s events.\n", 484 + event_type(type)); 485 + 486 + output[type].fields = 0; 487 + output[type].user_set = true; 488 + output[type].wildcard_set = false; 489 + 490 + } else { 491 + tok = str; 492 + if (strlen(str) == 0) { 493 + fprintf(stderr, 494 + "Cannot set fields to 'none' for all event types.\n"); 495 + rc = -EINVAL; 496 + goto out; 497 + } 498 + 499 + if (output_set_by_user()) 500 + pr_warning("Overriding previous field request for all events.\n"); 501 + 502 + for (j = 0; j < PERF_TYPE_MAX; ++j) { 503 + output[j].fields = 0; 504 + output[j].user_set = true; 505 + output[j].wildcard_set = true; 506 + } 590 507 } 591 508 592 - output_fields[type] = 0; 593 - while (1) { 594 - tok = strtok(NULL, ","); 595 - if (!tok) 596 - break; 509 + tok = strtok(tok, ","); 510 + while (tok) { 597 511 for (i = 0; i < imax; ++i) { 598 - if (strcmp(tok, all_output_options[i].str) == 0) { 599 - output_fields[type] |= all_output_options[i].field; 512 + if (strcmp(tok, all_output_options[i].str) == 0) 600 513 break; 601 - } 602 514 } 603 515 if (i == imax) { 604 - fprintf(stderr, "Invalid field requested."); 516 + fprintf(stderr, "Invalid field requested.\n"); 605 517 rc = -EINVAL; 606 - break; 518 + goto out; 519 + } 520 + 521 + if (type == -1) { 522 + /* add user option to all events types for 523 + * which it is valid 524 + */ 525 + for (j = 0; j < PERF_TYPE_MAX; ++j) { 526 + if (output[j].invalid_fields & all_output_options[i].field) { 527 + pr_warning("\'%s\' not valid for %s events. Ignoring.\n", 528 + all_output_options[i].str, event_type(j)); 529 + } else 530 + output[j].fields |= all_output_options[i].field; 531 + } 532 + } else { 533 + if (output[type].invalid_fields & all_output_options[i].field) { 534 + fprintf(stderr, "\'%s\' not valid for %s events.\n", 535 + all_output_options[i].str, event_type(type)); 536 + 537 + rc = -EINVAL; 538 + goto out; 539 + } 540 + output[type].fields |= all_output_options[i].field; 541 + } 542 + 543 + tok = strtok(NULL, ","); 544 + } 545 + 546 + if (type >= 0) { 547 + if (output[type].fields == 0) { 548 + pr_debug("No fields requested for %s type. " 549 + "Events will not be displayed.\n", event_type(type)); 607 550 } 608 551 } 609 552 610 - if (output_fields[type] == 0) { 611 - pr_debug("No fields requested for %s type. " 612 - "Events will not be displayed\n", event_type(type)); 613 - } 614 - 615 - output_set_by_user = true; 616 - 553 + out: 617 554 free(str); 618 555 return rc; 619 556 } ··· 986 829 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 987 830 "Look for files with symbols relative to this directory"), 988 831 OPT_CALLBACK('f', "fields", NULL, "str", 989 - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym", 832 + "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym", 990 833 parse_output_fields), 991 834 992 835 OPT_END() ··· 1177 1020 struct stat perf_stat; 1178 1021 int input; 1179 1022 1180 - if (output_set_by_user) { 1023 + if (output_set_by_user()) { 1181 1024 fprintf(stderr, 1182 1025 "custom fields not supported for generated scripts"); 1183 1026 return -1; ··· 1216 1059 goto out; 1217 1060 pr_debug("perf script started with script %s\n\n", script_name); 1218 1061 } 1062 + 1063 + 1064 + err = perf_session__check_output_opt(session); 1065 + if (err < 0) 1066 + goto out; 1219 1067 1220 1068 err = __cmd_script(session); 1221 1069
+510 -63
tools/perf/builtin-stat.c
··· 6 6 * 7 7 * Sample output: 8 8 9 - $ perf stat ~/hackbench 10 10 - Time: 0.104 9 + $ perf stat ./hackbench 10 11 10 12 - Performance counter stats for '/home/mingo/hackbench': 11 + Time: 0.118 13 12 14 - 1255.538611 task clock ticks # 10.143 CPU utilization factor 15 - 54011 context switches # 0.043 M/sec 16 - 385 CPU migrations # 0.000 M/sec 17 - 17755 pagefaults # 0.014 M/sec 18 - 3808323185 CPU cycles # 3033.219 M/sec 19 - 1575111190 instructions # 1254.530 M/sec 20 - 17367895 cache references # 13.833 M/sec 21 - 7674421 cache misses # 6.112 M/sec 13 + Performance counter stats for './hackbench 10': 22 14 23 - Wall-clock time elapsed: 123.786620 msecs 15 + 1708.761321 task-clock # 11.037 CPUs utilized 16 + 41,190 context-switches # 0.024 M/sec 17 + 6,735 CPU-migrations # 0.004 M/sec 18 + 17,318 page-faults # 0.010 M/sec 19 + 5,205,202,243 cycles # 3.046 GHz 20 + 3,856,436,920 stalled-cycles-frontend # 74.09% frontend cycles idle 21 + 1,600,790,871 stalled-cycles-backend # 30.75% backend cycles idle 22 + 2,603,501,247 instructions # 0.50 insns per cycle 23 + # 1.48 stalled cycles per insn 24 + 484,357,498 branches # 283.455 M/sec 25 + 6,388,934 branch-misses # 1.32% of all branches 26 + 27 + 0.154822978 seconds time elapsed 24 28 25 29 * 26 - * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 30 + * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 27 31 * 28 32 * Improvements and fixes by: 29 33 * ··· 50 46 #include "util/evlist.h" 51 47 #include "util/evsel.h" 52 48 #include "util/debug.h" 49 + #include "util/color.h" 53 50 #include "util/header.h" 54 51 #include "util/cpumap.h" 55 52 #include "util/thread.h" ··· 70 65 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 71 66 72 67 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 68 + { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 69 + { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 73 70 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 74 71 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 75 72 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 76 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES }, 77 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES }, 78 73 79 74 }; 75 + 76 + /* 77 + * Detailed stats (-d), covering the L1 and last level data caches: 78 + */ 79 + static struct perf_event_attr detailed_attrs[] = { 80 + 81 + { .type = PERF_TYPE_HW_CACHE, 82 + .config = 83 + PERF_COUNT_HW_CACHE_L1D << 0 | 84 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 85 + (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 86 + 87 + { .type = PERF_TYPE_HW_CACHE, 88 + .config = 89 + PERF_COUNT_HW_CACHE_L1D << 0 | 90 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 91 + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 92 + 93 + { .type = PERF_TYPE_HW_CACHE, 94 + .config = 95 + PERF_COUNT_HW_CACHE_LL << 0 | 96 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 97 + (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 98 + 99 + { .type = PERF_TYPE_HW_CACHE, 100 + .config = 101 + PERF_COUNT_HW_CACHE_LL << 0 | 102 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 103 + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 104 + }; 105 + 106 + /* 107 + * Very detailed stats (-d -d), covering the instruction cache and the TLB caches: 108 + */ 109 + static struct perf_event_attr very_detailed_attrs[] = { 110 + 111 + { .type = PERF_TYPE_HW_CACHE, 112 + .config = 113 + PERF_COUNT_HW_CACHE_L1I << 0 | 114 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 115 + (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 116 + 117 + { .type = PERF_TYPE_HW_CACHE, 118 + .config = 119 + PERF_COUNT_HW_CACHE_L1I << 0 | 120 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 121 + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 122 + 123 + { .type = PERF_TYPE_HW_CACHE, 124 + .config = 125 + PERF_COUNT_HW_CACHE_DTLB << 0 | 126 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 127 + (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 128 + 129 + { .type = PERF_TYPE_HW_CACHE, 130 + .config = 131 + PERF_COUNT_HW_CACHE_DTLB << 0 | 132 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 133 + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 134 + 135 + { .type = PERF_TYPE_HW_CACHE, 136 + .config = 137 + PERF_COUNT_HW_CACHE_ITLB << 0 | 138 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 139 + (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 140 + 141 + { .type = PERF_TYPE_HW_CACHE, 142 + .config = 143 + PERF_COUNT_HW_CACHE_ITLB << 0 | 144 + (PERF_COUNT_HW_CACHE_OP_READ << 8) | 145 + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 146 + 147 + }; 148 + 149 + /* 150 + * Very, very detailed stats (-d -d -d), adding prefetch events: 151 + */ 152 + static struct perf_event_attr very_very_detailed_attrs[] = { 153 + 154 + { .type = PERF_TYPE_HW_CACHE, 155 + .config = 156 + PERF_COUNT_HW_CACHE_L1D << 0 | 157 + (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 158 + (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 159 + 160 + { .type = PERF_TYPE_HW_CACHE, 161 + .config = 162 + PERF_COUNT_HW_CACHE_L1D << 0 | 163 + (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 164 + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 165 + }; 166 + 167 + 80 168 81 169 struct perf_evlist *evsel_list; 82 170 ··· 184 86 static pid_t target_tid = -1; 185 87 static pid_t child_pid = -1; 186 88 static bool null_run = false; 89 + static int detailed_run = 0; 90 + static bool sync_run = false; 187 91 static bool big_num = true; 188 92 static int big_num_opt = -1; 189 93 static const char *cpu_list; ··· 256 156 257 157 struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 258 158 struct stats runtime_cycles_stats[MAX_NR_CPUS]; 159 + struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS]; 160 + struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS]; 259 161 struct stats runtime_branches_stats[MAX_NR_CPUS]; 162 + struct stats runtime_cacherefs_stats[MAX_NR_CPUS]; 163 + struct stats runtime_l1_dcache_stats[MAX_NR_CPUS]; 164 + struct stats runtime_l1_icache_stats[MAX_NR_CPUS]; 165 + struct stats runtime_ll_cache_stats[MAX_NR_CPUS]; 166 + struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; 167 + struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 260 168 struct stats walltime_nsecs_stats; 261 169 262 170 static int create_perf_stat_counter(struct perf_evsel *evsel) ··· 301 193 } 302 194 303 195 /* 196 + * Update various tracking values we maintain to print 197 + * more semantic information such as miss/hit ratios, 198 + * instruction rates, etc: 199 + */ 200 + static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 201 + { 202 + if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 203 + update_stats(&runtime_nsecs_stats[0], count[0]); 204 + else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 205 + update_stats(&runtime_cycles_stats[0], count[0]); 206 + else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 207 + update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 208 + else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 209 + update_stats(&runtime_stalled_cycles_back_stats[0], count[0]); 210 + else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 211 + update_stats(&runtime_branches_stats[0], count[0]); 212 + else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 213 + update_stats(&runtime_cacherefs_stats[0], count[0]); 214 + else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 215 + update_stats(&runtime_l1_dcache_stats[0], count[0]); 216 + else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 217 + update_stats(&runtime_l1_icache_stats[0], count[0]); 218 + else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 219 + update_stats(&runtime_ll_cache_stats[0], count[0]); 220 + else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 221 + update_stats(&runtime_dtlb_cache_stats[0], count[0]); 222 + else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 223 + update_stats(&runtime_itlb_cache_stats[0], count[0]); 224 + } 225 + 226 + /* 304 227 * Read out the results of a single counter: 305 228 * aggregate counts across CPUs in system-wide mode 306 229 */ ··· 356 217 /* 357 218 * Save the full runtime - to allow normalization during printout: 358 219 */ 359 - if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 360 - update_stats(&runtime_nsecs_stats[0], count[0]); 361 - if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 362 - update_stats(&runtime_cycles_stats[0], count[0]); 363 - if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 364 - update_stats(&runtime_branches_stats[0], count[0]); 220 + update_shadow_stats(counter, count); 365 221 366 222 return 0; 367 223 } ··· 376 242 377 243 count = counter->counts->cpu[cpu].values; 378 244 379 - if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 380 - update_stats(&runtime_nsecs_stats[cpu], count[0]); 381 - if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 382 - update_stats(&runtime_cycles_stats[cpu], count[0]); 383 - if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 384 - update_stats(&runtime_branches_stats[cpu], count[0]); 245 + update_shadow_stats(counter, count); 385 246 } 386 247 387 248 return 0; ··· 444 315 445 316 list_for_each_entry(counter, &evsel_list->entries, node) { 446 317 if (create_perf_stat_counter(counter) < 0) { 447 - if (errno == -EPERM || errno == -EACCES) { 318 + if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) { 319 + if (verbose) 320 + ui__warning("%s event is not supported by the kernel.\n", 321 + event_name(counter)); 322 + continue; 323 + } 324 + 325 + if (errno == EPERM || errno == EACCES) { 448 326 error("You may not have permission to collect %sstats.\n" 449 327 "\t Consider tweaking" 450 328 " /proc/sys/kernel/perf_event_paranoid or running as root.", 451 329 system_wide ? "system-wide " : ""); 452 - } else if (errno == ENOENT) { 453 - error("%s event is not supported. ", event_name(counter)); 454 330 } else { 455 331 error("open_counter returned with %d (%s). " 456 332 "/bin/dmesg may provide additional information.\n", ··· 506 372 return WEXITSTATUS(status); 507 373 } 508 374 375 + static void print_noise_pct(double total, double avg) 376 + { 377 + double pct = 0.0; 378 + 379 + if (avg) 380 + pct = 100.0*total/avg; 381 + 382 + fprintf(stderr, " ( +-%6.2f%% )", pct); 383 + } 384 + 509 385 static void print_noise(struct perf_evsel *evsel, double avg) 510 386 { 511 387 struct perf_stat *ps; ··· 524 380 return; 525 381 526 382 ps = evsel->priv; 527 - fprintf(stderr, " ( +- %7.3f%% )", 528 - 100 * stddev_stats(&ps->res_stats[0]) / avg); 383 + print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 529 384 } 530 385 531 386 static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) 532 387 { 533 388 double msecs = avg / 1e6; 534 389 char cpustr[16] = { '\0', }; 535 - const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s"; 390 + const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s"; 536 391 537 392 if (no_aggr) 538 393 sprintf(cpustr, "CPU%*d%s", ··· 547 404 return; 548 405 549 406 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 550 - fprintf(stderr, " # %10.3f CPUs ", 551 - avg / avg_stats(&walltime_nsecs_stats)); 407 + fprintf(stderr, " # %8.3f CPUs utilized ", avg / avg_stats(&walltime_nsecs_stats)); 408 + } 409 + 410 + static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 411 + { 412 + double total, ratio = 0.0; 413 + const char *color; 414 + 415 + total = avg_stats(&runtime_cycles_stats[cpu]); 416 + 417 + if (total) 418 + ratio = avg / total * 100.0; 419 + 420 + color = PERF_COLOR_NORMAL; 421 + if (ratio > 50.0) 422 + color = PERF_COLOR_RED; 423 + else if (ratio > 30.0) 424 + color = PERF_COLOR_MAGENTA; 425 + else if (ratio > 10.0) 426 + color = PERF_COLOR_YELLOW; 427 + 428 + fprintf(stderr, " # "); 429 + color_fprintf(stderr, color, "%6.2f%%", ratio); 430 + fprintf(stderr, " frontend cycles idle "); 431 + } 432 + 433 + static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) 434 + { 435 + double total, ratio = 0.0; 436 + const char *color; 437 + 438 + total = avg_stats(&runtime_cycles_stats[cpu]); 439 + 440 + if (total) 441 + ratio = avg / total * 100.0; 442 + 443 + color = PERF_COLOR_NORMAL; 444 + if (ratio > 75.0) 445 + color = PERF_COLOR_RED; 446 + else if (ratio > 50.0) 447 + color = PERF_COLOR_MAGENTA; 448 + else if (ratio > 20.0) 449 + color = PERF_COLOR_YELLOW; 450 + 451 + fprintf(stderr, " # "); 452 + color_fprintf(stderr, color, "%6.2f%%", ratio); 453 + fprintf(stderr, " backend cycles idle "); 454 + } 455 + 456 + static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 457 + { 458 + double total, ratio = 0.0; 459 + const char *color; 460 + 461 + total = avg_stats(&runtime_branches_stats[cpu]); 462 + 463 + if (total) 464 + ratio = avg / total * 100.0; 465 + 466 + color = PERF_COLOR_NORMAL; 467 + if (ratio > 20.0) 468 + color = PERF_COLOR_RED; 469 + else if (ratio > 10.0) 470 + color = PERF_COLOR_MAGENTA; 471 + else if (ratio > 5.0) 472 + color = PERF_COLOR_YELLOW; 473 + 474 + fprintf(stderr, " # "); 475 + color_fprintf(stderr, color, "%6.2f%%", ratio); 476 + fprintf(stderr, " of all branches "); 477 + } 478 + 479 + static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 480 + { 481 + double total, ratio = 0.0; 482 + const char *color; 483 + 484 + total = avg_stats(&runtime_l1_dcache_stats[cpu]); 485 + 486 + if (total) 487 + ratio = avg / total * 100.0; 488 + 489 + color = PERF_COLOR_NORMAL; 490 + if (ratio > 20.0) 491 + color = PERF_COLOR_RED; 492 + else if (ratio > 10.0) 493 + color = PERF_COLOR_MAGENTA; 494 + else if (ratio > 5.0) 495 + color = PERF_COLOR_YELLOW; 496 + 497 + fprintf(stderr, " # "); 498 + color_fprintf(stderr, color, "%6.2f%%", ratio); 499 + fprintf(stderr, " of all L1-dcache hits "); 500 + } 501 + 502 + static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 503 + { 504 + double total, ratio = 0.0; 505 + const char *color; 506 + 507 + total = avg_stats(&runtime_l1_icache_stats[cpu]); 508 + 509 + if (total) 510 + ratio = avg / total * 100.0; 511 + 512 + color = PERF_COLOR_NORMAL; 513 + if (ratio > 20.0) 514 + color = PERF_COLOR_RED; 515 + else if (ratio > 10.0) 516 + color = PERF_COLOR_MAGENTA; 517 + else if (ratio > 5.0) 518 + color = PERF_COLOR_YELLOW; 519 + 520 + fprintf(stderr, " # "); 521 + color_fprintf(stderr, color, "%6.2f%%", ratio); 522 + fprintf(stderr, " of all L1-icache hits "); 523 + } 524 + 525 + static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 526 + { 527 + double total, ratio = 0.0; 528 + const char *color; 529 + 530 + total = avg_stats(&runtime_dtlb_cache_stats[cpu]); 531 + 532 + if (total) 533 + ratio = avg / total * 100.0; 534 + 535 + color = PERF_COLOR_NORMAL; 536 + if (ratio > 20.0) 537 + color = PERF_COLOR_RED; 538 + else if (ratio > 10.0) 539 + color = PERF_COLOR_MAGENTA; 540 + else if (ratio > 5.0) 541 + color = PERF_COLOR_YELLOW; 542 + 543 + fprintf(stderr, " # "); 544 + color_fprintf(stderr, color, "%6.2f%%", ratio); 545 + fprintf(stderr, " of all dTLB cache hits "); 546 + } 547 + 548 + static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 549 + { 550 + double total, ratio = 0.0; 551 + const char *color; 552 + 553 + total = avg_stats(&runtime_itlb_cache_stats[cpu]); 554 + 555 + if (total) 556 + ratio = avg / total * 100.0; 557 + 558 + color = PERF_COLOR_NORMAL; 559 + if (ratio > 20.0) 560 + color = PERF_COLOR_RED; 561 + else if (ratio > 10.0) 562 + color = PERF_COLOR_MAGENTA; 563 + else if (ratio > 5.0) 564 + color = PERF_COLOR_YELLOW; 565 + 566 + fprintf(stderr, " # "); 567 + color_fprintf(stderr, color, "%6.2f%%", ratio); 568 + fprintf(stderr, " of all iTLB cache hits "); 569 + } 570 + 571 + static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 572 + { 573 + double total, ratio = 0.0; 574 + const char *color; 575 + 576 + total = avg_stats(&runtime_ll_cache_stats[cpu]); 577 + 578 + if (total) 579 + ratio = avg / total * 100.0; 580 + 581 + color = PERF_COLOR_NORMAL; 582 + if (ratio > 20.0) 583 + color = PERF_COLOR_RED; 584 + else if (ratio > 10.0) 585 + color = PERF_COLOR_MAGENTA; 586 + else if (ratio > 5.0) 587 + color = PERF_COLOR_YELLOW; 588 + 589 + fprintf(stderr, " # "); 590 + color_fprintf(stderr, color, "%6.2f%%", ratio); 591 + fprintf(stderr, " of all LL-cache hits "); 552 592 } 553 593 554 594 static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) ··· 743 417 if (csv_output) 744 418 fmt = "%s%.0f%s%s"; 745 419 else if (big_num) 746 - fmt = "%s%'18.0f%s%-24s"; 420 + fmt = "%s%'18.0f%s%-25s"; 747 421 else 748 - fmt = "%s%18.0f%s%-24s"; 422 + fmt = "%s%18.0f%s%-25s"; 749 423 750 424 if (no_aggr) 751 425 sprintf(cpustr, "CPU%*d%s", ··· 768 442 if (total) 769 443 ratio = avg / total; 770 444 771 - fprintf(stderr, " # %10.3f IPC ", ratio); 445 + fprintf(stderr, " # %5.2f insns per cycle ", ratio); 446 + 447 + total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 448 + total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 449 + 450 + if (total && avg) { 451 + ratio = total / avg; 452 + fprintf(stderr, "\n # %5.2f stalled cycles per insn", ratio); 453 + } 454 + 772 455 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 773 456 runtime_branches_stats[cpu].n != 0) { 774 - total = avg_stats(&runtime_branches_stats[cpu]); 457 + print_branch_misses(cpu, evsel, avg); 458 + } else if ( 459 + evsel->attr.type == PERF_TYPE_HW_CACHE && 460 + evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | 461 + ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 462 + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 463 + runtime_l1_dcache_stats[cpu].n != 0) { 464 + print_l1_dcache_misses(cpu, evsel, avg); 465 + } else if ( 466 + evsel->attr.type == PERF_TYPE_HW_CACHE && 467 + evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | 468 + ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 469 + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 470 + runtime_l1_icache_stats[cpu].n != 0) { 471 + print_l1_icache_misses(cpu, evsel, avg); 472 + } else if ( 473 + evsel->attr.type == PERF_TYPE_HW_CACHE && 474 + evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | 475 + ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 476 + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 477 + runtime_dtlb_cache_stats[cpu].n != 0) { 478 + print_dtlb_cache_misses(cpu, evsel, avg); 479 + } else if ( 480 + evsel->attr.type == PERF_TYPE_HW_CACHE && 481 + evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | 482 + ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 483 + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 484 + runtime_itlb_cache_stats[cpu].n != 0) { 485 + print_itlb_cache_misses(cpu, evsel, avg); 486 + } else if ( 487 + evsel->attr.type == PERF_TYPE_HW_CACHE && 488 + evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | 489 + ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 490 + ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 491 + runtime_ll_cache_stats[cpu].n != 0) { 492 + print_ll_cache_misses(cpu, evsel, avg); 493 + } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) && 494 + runtime_cacherefs_stats[cpu].n != 0) { 495 + total = avg_stats(&runtime_cacherefs_stats[cpu]); 775 496 776 497 if (total) 777 498 ratio = avg * 100 / total; 778 499 779 - fprintf(stderr, " # %10.3f %% ", ratio); 500 + fprintf(stderr, " # %8.3f %% of all cache refs ", ratio); 780 501 502 + } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 503 + print_stalled_cycles_frontend(cpu, evsel, avg); 504 + } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { 505 + print_stalled_cycles_backend(cpu, evsel, avg); 506 + } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 507 + total = avg_stats(&runtime_nsecs_stats[cpu]); 508 + 509 + if (total) 510 + ratio = 1.0 * avg / total; 511 + 512 + fprintf(stderr, " # %8.3f GHz ", ratio); 781 513 } else if (runtime_nsecs_stats[cpu].n != 0) { 782 514 total = avg_stats(&runtime_nsecs_stats[cpu]); 783 515 784 516 if (total) 785 517 ratio = 1000.0 * avg / total; 786 518 787 - fprintf(stderr, " # %10.3f M/sec", ratio); 519 + fprintf(stderr, " # %8.3f M/sec ", ratio); 520 + } else { 521 + fprintf(stderr, " "); 788 522 } 789 523 } 790 524 ··· 891 505 avg_enabled = avg_stats(&ps->res_stats[1]); 892 506 avg_running = avg_stats(&ps->res_stats[2]); 893 507 894 - fprintf(stderr, " (scaled from %.2f%%)", 895 - 100 * avg_running / avg_enabled); 508 + fprintf(stderr, " [%5.2f%%]", 100 * avg_running / avg_enabled); 896 509 } 897 510 fprintf(stderr, "\n"); 898 511 } ··· 933 548 if (!csv_output) { 934 549 print_noise(counter, 1.0); 935 550 936 - if (run != ena) { 937 - fprintf(stderr, " (scaled from %.2f%%)", 938 - 100.0 * run / ena); 939 - } 551 + if (run != ena) 552 + fprintf(stderr, " (%.2f%%)", 100.0 * run / ena); 940 553 } 941 554 fputc('\n', stderr); 942 555 } ··· 974 591 } 975 592 976 593 if (!csv_output) { 977 - fprintf(stderr, "\n"); 978 - fprintf(stderr, " %18.9f seconds time elapsed", 594 + if (!null_run) 595 + fprintf(stderr, "\n"); 596 + fprintf(stderr, " %17.9f seconds time elapsed", 979 597 avg_stats(&walltime_nsecs_stats)/1e9); 980 598 if (run_count > 1) { 981 - fprintf(stderr, " ( +- %7.3f%% )", 982 - 100*stddev_stats(&walltime_nsecs_stats) / 983 - avg_stats(&walltime_nsecs_stats)); 599 + fprintf(stderr, " "); 600 + print_noise_pct(stddev_stats(&walltime_nsecs_stats), 601 + avg_stats(&walltime_nsecs_stats)); 984 602 } 985 603 fprintf(stderr, "\n\n"); 986 604 } ··· 1043 659 "repeat command and print average + stddev (max: 100)"), 1044 660 OPT_BOOLEAN('n', "null", &null_run, 1045 661 "null run - dont start any counters"), 662 + OPT_INCR('d', "detailed", &detailed_run, 663 + "detailed run - start a lot of events"), 664 + OPT_BOOLEAN('S', "sync", &sync_run, 665 + "call sync() before starting a run"), 1046 666 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1047 667 "print large numbers with thousands\' separators", 1048 668 stat__set_big_num), ··· 1061 673 parse_cgroups), 1062 674 OPT_END() 1063 675 }; 676 + 677 + /* 678 + * Add default attributes, if there were no attributes specified or 679 + * if -d/--detailed, -d -d or -d -d -d is used: 680 + */ 681 + static int add_default_attributes(void) 682 + { 683 + struct perf_evsel *pos; 684 + size_t attr_nr = 0; 685 + size_t c; 686 + 687 + /* Set attrs if no event is selected and !null_run: */ 688 + if (null_run) 689 + return 0; 690 + 691 + if (!evsel_list->nr_entries) { 692 + for (c = 0; c < ARRAY_SIZE(default_attrs); c++) { 693 + pos = perf_evsel__new(default_attrs + c, c + attr_nr); 694 + if (pos == NULL) 695 + return -1; 696 + perf_evlist__add(evsel_list, pos); 697 + } 698 + attr_nr += c; 699 + } 700 + 701 + /* Detailed events get appended to the event list: */ 702 + 703 + if (detailed_run < 1) 704 + return 0; 705 + 706 + /* Append detailed run extra attributes: */ 707 + for (c = 0; c < ARRAY_SIZE(detailed_attrs); c++) { 708 + pos = perf_evsel__new(detailed_attrs + c, c + attr_nr); 709 + if (pos == NULL) 710 + return -1; 711 + perf_evlist__add(evsel_list, pos); 712 + } 713 + attr_nr += c; 714 + 715 + if (detailed_run < 2) 716 + return 0; 717 + 718 + /* Append very detailed run extra attributes: */ 719 + for (c = 0; c < ARRAY_SIZE(very_detailed_attrs); c++) { 720 + pos = perf_evsel__new(very_detailed_attrs + c, c + attr_nr); 721 + if (pos == NULL) 722 + return -1; 723 + perf_evlist__add(evsel_list, pos); 724 + } 725 + 726 + if (detailed_run < 3) 727 + return 0; 728 + 729 + /* Append very, very detailed run extra attributes: */ 730 + for (c = 0; c < ARRAY_SIZE(very_very_detailed_attrs); c++) { 731 + pos = perf_evsel__new(very_very_detailed_attrs + c, c + attr_nr); 732 + if (pos == NULL) 733 + return -1; 734 + perf_evlist__add(evsel_list, pos); 735 + } 736 + 737 + 738 + return 0; 739 + } 1064 740 1065 741 int cmd_stat(int argc, const char **argv, const char *prefix __used) 1066 742 { ··· 1171 719 usage_with_options(stat_usage, options); 1172 720 } 1173 721 1174 - /* Set attrs and nr_counters if no event is selected and !null_run */ 1175 - if (!null_run && !evsel_list->nr_entries) { 1176 - size_t c; 1177 - 1178 - for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) { 1179 - pos = perf_evsel__new(&default_attrs[c], c); 1180 - if (pos == NULL) 1181 - goto out; 1182 - perf_evlist__add(evsel_list, pos); 1183 - } 1184 - } 722 + if (add_default_attributes()) 723 + goto out; 1185 724 1186 725 if (target_pid != -1) 1187 726 target_tid = target_pid; ··· 1216 773 for (run_idx = 0; run_idx < run_count; run_idx++) { 1217 774 if (run_count != 1 && verbose) 1218 775 fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 776 + 777 + if (sync_run) 778 + sync(); 779 + 1219 780 status = run_perf_stat(argc, argv); 1220 781 } 1221 782
+188
tools/perf/config/utilities.mak
··· 1 + # This allows us to work with the newline character: 2 + define newline 3 + 4 + 5 + endef 6 + newline := $(newline) 7 + 8 + # nl-escape 9 + # 10 + # Usage: escape = $(call nl-escape[,escape]) 11 + # 12 + # This is used as the common way to specify 13 + # what should replace a newline when escaping 14 + # newlines; the default is a bizarre string. 15 + # 16 + nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n) 17 + 18 + # escape-nl 19 + # 20 + # Usage: escaped-text = $(call escape-nl,text[,escape]) 21 + # 22 + # GNU make's $(shell ...) function converts to a 23 + # single space each newline character in the output 24 + # produced during the expansion; this may not be 25 + # desirable. 26 + # 27 + # The only solution is to change each newline into 28 + # something that won't be converted, so that the 29 + # information can be recovered later with 30 + # $(call unescape-nl...) 31 + # 32 + escape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1)) 33 + 34 + # unescape-nl 35 + # 36 + # Usage: text = $(call unescape-nl,escaped-text[,escape]) 37 + # 38 + # See escape-nl. 39 + # 40 + unescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1)) 41 + 42 + # shell-escape-nl 43 + # 44 + # Usage: $(shell some-command | $(call shell-escape-nl[,escape])) 45 + # 46 + # Use this to escape newlines from within a shell call; 47 + # the default escape is a bizarre string. 48 + # 49 + # NOTE: The escape is used directly as a string constant 50 + # in an `awk' program that is delimited by shell 51 + # single-quotes, so be wary of the characters 52 + # that are chosen. 53 + # 54 + define shell-escape-nl 55 + awk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}' 56 + endef 57 + 58 + # shell-unescape-nl 59 + # 60 + # Usage: $(shell some-command | $(call shell-unescape-nl[,escape])) 61 + # 62 + # Use this to unescape newlines from within a shell call; 63 + # the default escape is a bizarre string. 64 + # 65 + # NOTE: The escape is used directly as an extended regular 66 + # expression constant in an `awk' program that is 67 + # delimited by shell single-quotes, so be wary 68 + # of the characters that are chosen. 69 + # 70 + # (The bash shell has a bug where `{gsub(...),...}' is 71 + # misinterpreted as a brace expansion; this can be 72 + # overcome by putting a space between `{' and `gsub'). 73 + # 74 + define shell-unescape-nl 75 + awk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }' 76 + endef 77 + 78 + # escape-for-shell-sq 79 + # 80 + # Usage: embeddable-text = $(call escape-for-shell-sq,text) 81 + # 82 + # This function produces text that is suitable for 83 + # embedding in a shell string that is delimited by 84 + # single-quotes. 85 + # 86 + escape-for-shell-sq = $(subst ','\'',$(1)) 87 + 88 + # shell-sq 89 + # 90 + # Usage: single-quoted-and-escaped-text = $(call shell-sq,text) 91 + # 92 + shell-sq = '$(escape-for-shell-sq)' 93 + 94 + # shell-wordify 95 + # 96 + # Usage: wordified-text = $(call shell-wordify,text) 97 + # 98 + # For instance: 99 + # 100 + # |define text 101 + # |hello 102 + # |world 103 + # |endef 104 + # | 105 + # |target: 106 + # | echo $(call shell-wordify,$(text)) 107 + # 108 + # At least GNU make gets confused by expanding a newline 109 + # within the context of a command line of a makefile rule 110 + # (this is in constrast to a `$(shell ...)' function call, 111 + # which can handle it just fine). 112 + # 113 + # This function avoids the problem by producing a string 114 + # that works as a shell word, regardless of whether or 115 + # not it contains a newline. 116 + # 117 + # If the text to be wordified contains a newline, then 118 + # an intrictate shell command substitution is constructed 119 + # to render the text as a single line; when the shell 120 + # processes the resulting escaped text, it transforms 121 + # it into the original unescaped text. 122 + # 123 + # If the text does not contain a newline, then this function 124 + # produces the same results as the `$(shell-sq)' function. 125 + # 126 + shell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq)) 127 + define _sw-esc-nl 128 + "$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))" 129 + endef 130 + 131 + # is-absolute 132 + # 133 + # Usage: bool-value = $(call is-absolute,path) 134 + # 135 + is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) 136 + 137 + # lookup 138 + # 139 + # Usage: absolute-executable-path-or-empty = $(call lookup,path) 140 + # 141 + # (It's necessary to use `sh -c' because GNU make messes up by 142 + # trying too hard and getting things wrong). 143 + # 144 + lookup = $(call unescape-nl,$(shell sh -c $(_l-sh))) 145 + _l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,)) 146 + 147 + # is-executable 148 + # 149 + # Usage: bool-value = $(call is-executable,path) 150 + # 151 + # (It's necessary to use `sh -c' because GNU make messes up by 152 + # trying too hard and getting things wrong). 153 + # 154 + is-executable = $(call _is-executable-helper,$(shell-sq)) 155 + _is-executable-helper = $(shell sh -c $(_is-executable-sh)) 156 + _is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y) 157 + 158 + # get-executable 159 + # 160 + # Usage: absolute-executable-path-or-empty = $(call get-executable,path) 161 + # 162 + # The goal is to get an absolute path for an executable; 163 + # the `command -v' is defined by POSIX, but it's not 164 + # necessarily very portable, so it's only used if 165 + # relative path resolution is requested, as determined 166 + # by the presence of a leading `/'. 167 + # 168 + get-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup))) 169 + _ge-abspath = $(if $(is-executable),$(1)) 170 + 171 + # get-supplied-or-default-executable 172 + # 173 + # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default) 174 + # 175 + define get-executable-or-default 176 + $(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) 177 + endef 178 + _ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2))) 179 + _gea_warn = $(warning The path '$(1)' is not executable.) 180 + _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 181 + 182 + # try-cc 183 + # Usage: option = $(call try-cc, source-to-build, cc-options) 184 + try-cc = $(shell sh -c \ 185 + 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \ 186 + echo "$(1)" | \ 187 + $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \ 188 + rm -f "$$TMP"')
+7 -9
tools/perf/feature-tests.mak tools/perf/config/feature-tests.mak
··· 79 79 endif 80 80 81 81 ifndef NO_LIBPYTHON 82 + define SOURCE_PYTHON_VERSION 83 + #include <Python.h> 84 + #if PY_VERSION_HEX >= 0x03000000 85 + #error 86 + #endif 87 + int main(void){} 88 + endef 82 89 define SOURCE_PYTHON_EMBED 83 90 #include <Python.h> 84 - 85 91 int main(void) 86 92 { 87 93 Py_Initialize(); ··· 126 120 return 0; 127 121 } 128 122 endef 129 - 130 - # try-cc 131 - # Usage: option = $(call try-cc, source-to-build, cc-options) 132 - try-cc = $(shell sh -c \ 133 - 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \ 134 - echo "$(1)" | \ 135 - $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \ 136 - rm -f "$$TMP"')
+8
tools/perf/util/include/asm/alternative-asm.h
··· 1 + #ifndef _PERF_ASM_ALTERNATIVE_ASM_H 2 + #define _PERF_ASM_ALTERNATIVE_ASM_H 3 + 4 + /* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */ 5 + 6 + #define altinstruction_entry # 7 + 8 + #endif
+71 -50
tools/perf/util/parse-events.c
··· 31 31 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 32 32 33 33 static struct event_symbol event_symbols[] = { 34 - { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 35 - { CHW(INSTRUCTIONS), "instructions", "" }, 36 - { CHW(CACHE_REFERENCES), "cache-references", "" }, 37 - { CHW(CACHE_MISSES), "cache-misses", "" }, 38 - { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 39 - { CHW(BRANCH_MISSES), "branch-misses", "" }, 40 - { CHW(BUS_CYCLES), "bus-cycles", "" }, 34 + { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 35 + { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, 36 + { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, 37 + { CHW(INSTRUCTIONS), "instructions", "" }, 38 + { CHW(CACHE_REFERENCES), "cache-references", "" }, 39 + { CHW(CACHE_MISSES), "cache-misses", "" }, 40 + { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 41 + { CHW(BRANCH_MISSES), "branch-misses", "" }, 42 + { CHW(BUS_CYCLES), "bus-cycles", "" }, 41 43 42 - { CSW(CPU_CLOCK), "cpu-clock", "" }, 43 - { CSW(TASK_CLOCK), "task-clock", "" }, 44 - { CSW(PAGE_FAULTS), "page-faults", "faults" }, 45 - { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 46 - { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 47 - { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 48 - { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 49 - { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 50 - { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 44 + { CSW(CPU_CLOCK), "cpu-clock", "" }, 45 + { CSW(TASK_CLOCK), "task-clock", "" }, 46 + { CSW(PAGE_FAULTS), "page-faults", "faults" }, 47 + { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 48 + { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 49 + { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 50 + { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 51 + { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 52 + { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 51 53 }; 52 54 53 55 #define __PERF_EVENT_FIELD(config, name) \ 54 56 ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 55 57 56 - #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 58 + #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 57 59 #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 58 - #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 60 + #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 59 61 #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 60 62 61 - static const char *hw_event_names[] = { 63 + static const char *hw_event_names[PERF_COUNT_HW_MAX] = { 62 64 "cycles", 63 65 "instructions", 64 66 "cache-references", ··· 68 66 "branches", 69 67 "branch-misses", 70 68 "bus-cycles", 69 + "stalled-cycles-frontend", 70 + "stalled-cycles-backend", 71 71 }; 72 72 73 - static const char *sw_event_names[] = { 74 - "cpu-clock-msecs", 75 - "task-clock-msecs", 73 + static const char *sw_event_names[PERF_COUNT_SW_MAX] = { 74 + "cpu-clock", 75 + "task-clock", 76 76 "page-faults", 77 77 "context-switches", 78 78 "CPU-migrations", ··· 311 307 312 308 switch (type) { 313 309 case PERF_TYPE_HARDWARE: 314 - if (config < PERF_COUNT_HW_MAX) 310 + if (config < PERF_COUNT_HW_MAX && hw_event_names[config]) 315 311 return hw_event_names[config]; 316 312 return "unknown-hardware"; 317 313 ··· 337 333 } 338 334 339 335 case PERF_TYPE_SOFTWARE: 340 - if (config < PERF_COUNT_SW_MAX) 336 + if (config < PERF_COUNT_SW_MAX && sw_event_names[config]) 341 337 return sw_event_names[config]; 342 338 return "unknown-software"; 343 339 ··· 652 648 int n; 653 649 654 650 n = strlen(event_symbols[i].symbol); 655 - if (!strncmp(str, event_symbols[i].symbol, n)) 651 + if (!strncasecmp(str, event_symbols[i].symbol, n)) 656 652 return n; 657 653 658 654 n = strlen(event_symbols[i].alias); 659 - if (n) 660 - if (!strncmp(str, event_symbols[i].alias, n)) 655 + if (n) { 656 + if (!strncasecmp(str, event_symbols[i].alias, n)) 661 657 return n; 658 + } 659 + 662 660 return 0; 663 661 } 664 662 ··· 724 718 return EVT_FAILED; 725 719 } 726 720 727 - static enum event_result 721 + static int 728 722 parse_event_modifier(const char **strp, struct perf_event_attr *attr) 729 723 { 730 724 const char *str = *strp; 731 725 int exclude = 0; 732 726 int eu = 0, ek = 0, eh = 0, precise = 0; 733 727 734 - if (*str++ != ':') 728 + if (!*str) 735 729 return 0; 730 + 731 + if (*str == ',') 732 + return 0; 733 + 734 + if (*str++ != ':') 735 + return -1; 736 + 736 737 while (*str) { 737 738 if (*str == 'u') { 738 739 if (!exclude) ··· 760 747 761 748 ++str; 762 749 } 763 - if (str >= *strp + 2) { 764 - *strp = str; 765 - attr->exclude_user = eu; 766 - attr->exclude_kernel = ek; 767 - attr->exclude_hv = eh; 768 - attr->precise_ip = precise; 769 - return 1; 770 - } 750 + if (str < *strp + 2) 751 + return -1; 752 + 753 + *strp = str; 754 + 755 + attr->exclude_user = eu; 756 + attr->exclude_kernel = ek; 757 + attr->exclude_hv = eh; 758 + attr->precise_ip = precise; 759 + 771 760 return 0; 772 761 } 773 762 ··· 812 797 return EVT_FAILED; 813 798 814 799 modifier: 815 - parse_event_modifier(str, attr); 800 + if (parse_event_modifier(str, attr) < 0) { 801 + fprintf(stderr, "invalid event modifier: '%s'\n", *str); 802 + fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n"); 803 + 804 + return EVT_FAILED; 805 + } 816 806 817 807 return ret; 818 808 } ··· 932 912 933 913 snprintf(evt_path, MAXPATHLEN, "%s:%s", 934 914 sys_dirent.d_name, evt_dirent.d_name); 935 - printf(" %-42s [%s]\n", evt_path, 915 + printf(" %-50s [%s]\n", evt_path, 936 916 event_type_descriptors[PERF_TYPE_TRACEPOINT]); 937 917 } 938 918 closedir(evt_dir); ··· 997 977 else 998 978 snprintf(name, sizeof(name), "%s", syms->symbol); 999 979 1000 - printf(" %-42s [%s]\n", name, 980 + printf(" %-50s [%s]\n", name, 1001 981 event_type_descriptors[type]); 1002 982 } 1003 983 } ··· 1015 995 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 1016 996 char *name = event_cache_name(type, op, i); 1017 997 1018 - if (event_glob != NULL && 1019 - !strglobmatch(name, event_glob)) 998 + if (event_glob != NULL && !strglobmatch(name, event_glob)) 1020 999 continue; 1021 1000 1022 - printf(" %-42s [%s]\n", name, 1001 + printf(" %-50s [%s]\n", name, 1023 1002 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1024 1003 ++printed; 1025 1004 } ··· 1028 1009 return printed; 1029 1010 } 1030 1011 1012 + #define MAX_NAME_LEN 100 1013 + 1031 1014 /* 1032 1015 * Print the help text for the event symbols: 1033 1016 */ 1034 1017 void print_events(const char *event_glob) 1035 1018 { 1036 - struct event_symbol *syms = event_symbols; 1037 1019 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; 1038 - char name[40]; 1020 + struct event_symbol *syms = event_symbols; 1021 + char name[MAX_NAME_LEN]; 1039 1022 1040 1023 printf("\n"); 1041 1024 printf("List of pre-defined events (to be used in -e):\n"); ··· 1057 1036 continue; 1058 1037 1059 1038 if (strlen(syms->alias)) 1060 - sprintf(name, "%s OR %s", syms->symbol, syms->alias); 1039 + snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1061 1040 else 1062 - strcpy(name, syms->symbol); 1063 - printf(" %-42s [%s]\n", name, 1041 + strncpy(name, syms->symbol, MAX_NAME_LEN); 1042 + printf(" %-50s [%s]\n", name, 1064 1043 event_type_descriptors[type]); 1065 1044 1066 1045 prev_type = type; ··· 1077 1056 return; 1078 1057 1079 1058 printf("\n"); 1080 - printf(" %-42s [%s]\n", 1059 + printf(" %-50s [%s]\n", 1081 1060 "rNNN (see 'perf list --help' on how to encode it)", 1082 1061 event_type_descriptors[PERF_TYPE_RAW]); 1083 1062 printf("\n"); 1084 1063 1085 - printf(" %-42s [%s]\n", 1064 + printf(" %-50s [%s]\n", 1086 1065 "mem:<addr>[:access]", 1087 1066 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1088 1067 printf("\n");
+73
tools/perf/util/probe-finder.c
··· 1471 1471 return _param.retval; 1472 1472 } 1473 1473 1474 + struct pubname_callback_param { 1475 + char *function; 1476 + char *file; 1477 + Dwarf_Die *cu_die; 1478 + Dwarf_Die *sp_die; 1479 + int found; 1480 + }; 1481 + 1482 + static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) 1483 + { 1484 + struct pubname_callback_param *param = data; 1485 + 1486 + if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) { 1487 + if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) 1488 + return DWARF_CB_OK; 1489 + 1490 + if (die_compare_name(param->sp_die, param->function)) { 1491 + if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) 1492 + return DWARF_CB_OK; 1493 + 1494 + if (param->file && 1495 + strtailcmp(param->file, dwarf_decl_file(param->sp_die))) 1496 + return DWARF_CB_OK; 1497 + 1498 + param->found = 1; 1499 + return DWARF_CB_ABORT; 1500 + } 1501 + } 1502 + 1503 + return DWARF_CB_OK; 1504 + } 1505 + 1474 1506 /* Find probe points from debuginfo */ 1475 1507 static int find_probes(int fd, struct probe_finder *pf) 1476 1508 { ··· 1530 1498 1531 1499 off = 0; 1532 1500 line_list__init(&pf->lcache); 1501 + 1502 + /* Fastpath: lookup by function name from .debug_pubnames section */ 1503 + if (pp->function) { 1504 + struct pubname_callback_param pubname_param = { 1505 + .function = pp->function, 1506 + .file = pp->file, 1507 + .cu_die = &pf->cu_die, 1508 + .sp_die = &pf->sp_die, 1509 + .found = 0, 1510 + }; 1511 + struct dwarf_callback_param probe_param = { 1512 + .data = pf, 1513 + }; 1514 + 1515 + dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); 1516 + if (pubname_param.found) { 1517 + ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1518 + if (ret) 1519 + goto found; 1520 + } 1521 + } 1522 + 1533 1523 /* Loop on CUs (Compilation Unit) */ 1534 1524 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1535 1525 /* Get the DIE(Debugging Information Entry) of this CU */ ··· 1579 1525 } 1580 1526 off = noff; 1581 1527 } 1528 + 1529 + found: 1582 1530 line_list__free(&pf->lcache); 1583 1531 if (dwfl) 1584 1532 dwfl_end(dwfl); ··· 2002 1946 return -EBADF; 2003 1947 } 2004 1948 1949 + /* Fastpath: lookup by function name from .debug_pubnames section */ 1950 + if (lr->function) { 1951 + struct pubname_callback_param pubname_param = { 1952 + .function = lr->function, .file = lr->file, 1953 + .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; 1954 + struct dwarf_callback_param line_range_param = { 1955 + .data = (void *)&lf, .retval = 0}; 1956 + 1957 + dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); 1958 + if (pubname_param.found) { 1959 + line_range_search_cb(&lf.sp_die, &line_range_param); 1960 + if (lf.found) 1961 + goto found; 1962 + } 1963 + } 1964 + 2005 1965 /* Loop on CUs (Compilation Unit) */ 2006 1966 while (!lf.found && ret >= 0) { 2007 1967 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) ··· 2046 1974 off = noff; 2047 1975 } 2048 1976 1977 + found: 2049 1978 /* Store comp_dir */ 2050 1979 if (lf.found) { 2051 1980 comp_dir = cu_get_comp_dir(&lf.cu_die);
+2
tools/perf/util/probe-finder.h
··· 49 49 Dwarf_Addr addr; /* Address */ 50 50 const char *fname; /* Real file name */ 51 51 Dwarf_Die cu_die; /* Current CU */ 52 + Dwarf_Die sp_die; 52 53 struct list_head lcache; /* Line cache for lazy match */ 53 54 54 55 /* For variable searching */ ··· 84 83 int lno_s; /* Start line number */ 85 84 int lno_e; /* End line number */ 86 85 Dwarf_Die cu_die; /* Current CU */ 86 + Dwarf_Die sp_die; 87 87 int found; 88 88 }; 89 89
+3
tools/perf/util/python.c
··· 810 810 { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS }, 811 811 { "COUNT_HW_CACHE_RESULT_MISS", PERF_COUNT_HW_CACHE_RESULT_MISS }, 812 812 813 + { "COUNT_HW_STALLED_CYCLES_FRONTEND", PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 814 + { "COUNT_HW_STALLED_CYCLES_BACKEND", PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 815 + 813 816 { "COUNT_SW_CPU_CLOCK", PERF_COUNT_SW_CPU_CLOCK }, 814 817 { "COUNT_SW_TASK_CLOCK", PERF_COUNT_SW_TASK_CLOCK }, 815 818 { "COUNT_SW_PAGE_FAULTS", PERF_COUNT_SW_PAGE_FAULTS },
+12
tools/perf/util/session.c
··· 1156 1156 return ret; 1157 1157 } 1158 1158 1159 + struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 1160 + unsigned int type) 1161 + { 1162 + struct perf_evsel *pos; 1163 + 1164 + list_for_each_entry(pos, &session->evlist->entries, node) { 1165 + if (pos->attr.type == type) 1166 + return pos; 1167 + } 1168 + return NULL; 1169 + } 1170 + 1159 1171 void perf_session__print_symbols(union perf_event *event, 1160 1172 struct perf_sample *sample, 1161 1173 struct perf_session *session)
+3
tools/perf/util/session.h
··· 162 162 session->sample_id_all, sample); 163 163 } 164 164 165 + struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 166 + unsigned int type); 167 + 165 168 void perf_session__print_symbols(union perf_event *event, 166 169 struct perf_sample *sample, 167 170 struct perf_session *session);
+320 -309
tools/perf/util/symbol.c
··· 31 31 #define NT_GNU_BUILD_ID 3 32 32 #endif 33 33 34 - static bool dso__build_id_equal(const struct dso *self, u8 *build_id); 34 + static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); 35 35 static int elf_read_build_id(Elf *elf, void *bf, size_t size); 36 36 static void dsos__add(struct list_head *head, struct dso *dso); 37 37 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 38 - static int dso__load_kernel_sym(struct dso *self, struct map *map, 38 + static int dso__load_kernel_sym(struct dso *dso, struct map *map, 39 39 symbol_filter_t filter); 40 - static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, 40 + static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 41 41 symbol_filter_t filter); 42 42 static int vmlinux_path__nr_entries; 43 43 static char **vmlinux_path; ··· 49 49 .symfs = "", 50 50 }; 51 51 52 - int dso__name_len(const struct dso *self) 52 + int dso__name_len(const struct dso *dso) 53 53 { 54 54 if (verbose) 55 - return self->long_name_len; 55 + return dso->long_name_len; 56 56 57 - return self->short_name_len; 57 + return dso->short_name_len; 58 58 } 59 59 60 - bool dso__loaded(const struct dso *self, enum map_type type) 60 + bool dso__loaded(const struct dso *dso, enum map_type type) 61 61 { 62 - return self->loaded & (1 << type); 62 + return dso->loaded & (1 << type); 63 63 } 64 64 65 - bool dso__sorted_by_name(const struct dso *self, enum map_type type) 65 + bool dso__sorted_by_name(const struct dso *dso, enum map_type type) 66 66 { 67 - return self->sorted_by_name & (1 << type); 67 + return dso->sorted_by_name & (1 << type); 68 68 } 69 69 70 - static void dso__set_sorted_by_name(struct dso *self, enum map_type type) 70 + static void dso__set_sorted_by_name(struct dso *dso, enum map_type type) 71 71 { 72 - self->sorted_by_name |= (1 << type); 72 + dso->sorted_by_name |= (1 << type); 73 73 } 74 74 75 75 bool symbol_type__is_a(char symbol_type, enum map_type map_type) ··· 84 84 } 85 85 } 86 86 87 - static void symbols__fixup_end(struct rb_root *self) 87 + static void symbols__fixup_end(struct rb_root *symbols) 88 88 { 89 - struct rb_node *nd, *prevnd = rb_first(self); 89 + struct rb_node *nd, *prevnd = rb_first(symbols); 90 90 struct symbol *curr, *prev; 91 91 92 92 if (prevnd == NULL) ··· 107 107 curr->end = roundup(curr->start, 4096); 108 108 } 109 109 110 - static void __map_groups__fixup_end(struct map_groups *self, enum map_type type) 110 + static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 111 111 { 112 112 struct map *prev, *curr; 113 - struct rb_node *nd, *prevnd = rb_first(&self->maps[type]); 113 + struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 114 114 115 115 if (prevnd == NULL) 116 116 return; ··· 130 130 curr->end = ~0ULL; 131 131 } 132 132 133 - static void map_groups__fixup_end(struct map_groups *self) 133 + static void map_groups__fixup_end(struct map_groups *mg) 134 134 { 135 135 int i; 136 136 for (i = 0; i < MAP__NR_TYPES; ++i) 137 - __map_groups__fixup_end(self, i); 137 + __map_groups__fixup_end(mg, i); 138 138 } 139 139 140 140 static struct symbol *symbol__new(u64 start, u64 len, u8 binding, 141 141 const char *name) 142 142 { 143 143 size_t namelen = strlen(name) + 1; 144 - struct symbol *self = calloc(1, (symbol_conf.priv_size + 145 - sizeof(*self) + namelen)); 146 - if (self == NULL) 144 + struct symbol *sym = calloc(1, (symbol_conf.priv_size + 145 + sizeof(*sym) + namelen)); 146 + if (sym == NULL) 147 147 return NULL; 148 148 149 149 if (symbol_conf.priv_size) 150 - self = ((void *)self) + symbol_conf.priv_size; 150 + sym = ((void *)sym) + symbol_conf.priv_size; 151 151 152 - self->start = start; 153 - self->end = len ? start + len - 1 : start; 154 - self->binding = binding; 155 - self->namelen = namelen - 1; 152 + sym->start = start; 153 + sym->end = len ? start + len - 1 : start; 154 + sym->binding = binding; 155 + sym->namelen = namelen - 1; 156 156 157 - pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, self->end); 157 + pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", 158 + __func__, name, start, sym->end); 159 + memcpy(sym->name, name, namelen); 158 160 159 - memcpy(self->name, name, namelen); 160 - 161 - return self; 161 + return sym; 162 162 } 163 163 164 - void symbol__delete(struct symbol *self) 164 + void symbol__delete(struct symbol *sym) 165 165 { 166 - free(((void *)self) - symbol_conf.priv_size); 166 + free(((void *)sym) - symbol_conf.priv_size); 167 167 } 168 168 169 - static size_t symbol__fprintf(struct symbol *self, FILE *fp) 169 + static size_t symbol__fprintf(struct symbol *sym, FILE *fp) 170 170 { 171 171 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", 172 - self->start, self->end, 173 - self->binding == STB_GLOBAL ? 'g' : 174 - self->binding == STB_LOCAL ? 'l' : 'w', 175 - self->name); 172 + sym->start, sym->end, 173 + sym->binding == STB_GLOBAL ? 'g' : 174 + sym->binding == STB_LOCAL ? 'l' : 'w', 175 + sym->name); 176 176 } 177 177 178 - void dso__set_long_name(struct dso *self, char *name) 178 + void dso__set_long_name(struct dso *dso, char *name) 179 179 { 180 180 if (name == NULL) 181 181 return; 182 - self->long_name = name; 183 - self->long_name_len = strlen(name); 182 + dso->long_name = name; 183 + dso->long_name_len = strlen(name); 184 184 } 185 185 186 - static void dso__set_short_name(struct dso *self, const char *name) 186 + static void dso__set_short_name(struct dso *dso, const char *name) 187 187 { 188 188 if (name == NULL) 189 189 return; 190 - self->short_name = name; 191 - self->short_name_len = strlen(name); 190 + dso->short_name = name; 191 + dso->short_name_len = strlen(name); 192 192 } 193 193 194 - static void dso__set_basename(struct dso *self) 194 + static void dso__set_basename(struct dso *dso) 195 195 { 196 - dso__set_short_name(self, basename(self->long_name)); 196 + dso__set_short_name(dso, basename(dso->long_name)); 197 197 } 198 198 199 199 struct dso *dso__new(const char *name) 200 200 { 201 - struct dso *self = calloc(1, sizeof(*self) + strlen(name) + 1); 201 + struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1); 202 202 203 - if (self != NULL) { 203 + if (dso != NULL) { 204 204 int i; 205 - strcpy(self->name, name); 206 - dso__set_long_name(self, self->name); 207 - dso__set_short_name(self, self->name); 205 + strcpy(dso->name, name); 206 + dso__set_long_name(dso, dso->name); 207 + dso__set_short_name(dso, dso->name); 208 208 for (i = 0; i < MAP__NR_TYPES; ++i) 209 - self->symbols[i] = self->symbol_names[i] = RB_ROOT; 210 - self->symtab_type = SYMTAB__NOT_FOUND; 211 - self->loaded = 0; 212 - self->sorted_by_name = 0; 213 - self->has_build_id = 0; 214 - self->kernel = DSO_TYPE_USER; 215 - INIT_LIST_HEAD(&self->node); 209 + dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 210 + dso->symtab_type = SYMTAB__NOT_FOUND; 211 + dso->loaded = 0; 212 + dso->sorted_by_name = 0; 213 + dso->has_build_id = 0; 214 + dso->kernel = DSO_TYPE_USER; 215 + INIT_LIST_HEAD(&dso->node); 216 216 } 217 217 218 - return self; 218 + return dso; 219 219 } 220 220 221 - static void symbols__delete(struct rb_root *self) 221 + static void symbols__delete(struct rb_root *symbols) 222 222 { 223 223 struct symbol *pos; 224 - struct rb_node *next = rb_first(self); 224 + struct rb_node *next = rb_first(symbols); 225 225 226 226 while (next) { 227 227 pos = rb_entry(next, struct symbol, rb_node); 228 228 next = rb_next(&pos->rb_node); 229 - rb_erase(&pos->rb_node, self); 229 + rb_erase(&pos->rb_node, symbols); 230 230 symbol__delete(pos); 231 231 } 232 232 } 233 233 234 - void dso__delete(struct dso *self) 234 + void dso__delete(struct dso *dso) 235 235 { 236 236 int i; 237 237 for (i = 0; i < MAP__NR_TYPES; ++i) 238 - symbols__delete(&self->symbols[i]); 239 - if (self->sname_alloc) 240 - free((char *)self->short_name); 241 - if (self->lname_alloc) 242 - free(self->long_name); 243 - free(self); 238 + symbols__delete(&dso->symbols[i]); 239 + if (dso->sname_alloc) 240 + free((char *)dso->short_name); 241 + if (dso->lname_alloc) 242 + free(dso->long_name); 243 + free(dso); 244 244 } 245 245 246 - void dso__set_build_id(struct dso *self, void *build_id) 246 + void dso__set_build_id(struct dso *dso, void *build_id) 247 247 { 248 - memcpy(self->build_id, build_id, sizeof(self->build_id)); 249 - self->has_build_id = 1; 248 + memcpy(dso->build_id, build_id, sizeof(dso->build_id)); 249 + dso->has_build_id = 1; 250 250 } 251 251 252 - static void symbols__insert(struct rb_root *self, struct symbol *sym) 252 + static void symbols__insert(struct rb_root *symbols, struct symbol *sym) 253 253 { 254 - struct rb_node **p = &self->rb_node; 254 + struct rb_node **p = &symbols->rb_node; 255 255 struct rb_node *parent = NULL; 256 256 const u64 ip = sym->start; 257 257 struct symbol *s; ··· 265 265 p = &(*p)->rb_right; 266 266 } 267 267 rb_link_node(&sym->rb_node, parent, p); 268 - rb_insert_color(&sym->rb_node, self); 268 + rb_insert_color(&sym->rb_node, symbols); 269 269 } 270 270 271 - static struct symbol *symbols__find(struct rb_root *self, u64 ip) 271 + static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) 272 272 { 273 273 struct rb_node *n; 274 274 275 - if (self == NULL) 275 + if (symbols == NULL) 276 276 return NULL; 277 277 278 - n = self->rb_node; 278 + n = symbols->rb_node; 279 279 280 280 while (n) { 281 281 struct symbol *s = rb_entry(n, struct symbol, rb_node); ··· 296 296 struct symbol sym; 297 297 }; 298 298 299 - static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym) 299 + static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) 300 300 { 301 - struct rb_node **p = &self->rb_node; 301 + struct rb_node **p = &symbols->rb_node; 302 302 struct rb_node *parent = NULL; 303 303 struct symbol_name_rb_node *symn, *s; 304 304 ··· 313 313 p = &(*p)->rb_right; 314 314 } 315 315 rb_link_node(&symn->rb_node, parent, p); 316 - rb_insert_color(&symn->rb_node, self); 316 + rb_insert_color(&symn->rb_node, symbols); 317 317 } 318 318 319 - static void symbols__sort_by_name(struct rb_root *self, struct rb_root *source) 319 + static void symbols__sort_by_name(struct rb_root *symbols, 320 + struct rb_root *source) 320 321 { 321 322 struct rb_node *nd; 322 323 323 324 for (nd = rb_first(source); nd; nd = rb_next(nd)) { 324 325 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 325 - symbols__insert_by_name(self, pos); 326 + symbols__insert_by_name(symbols, pos); 326 327 } 327 328 } 328 329 329 - static struct symbol *symbols__find_by_name(struct rb_root *self, const char *name) 330 + static struct symbol *symbols__find_by_name(struct rb_root *symbols, 331 + const char *name) 330 332 { 331 333 struct rb_node *n; 332 334 333 - if (self == NULL) 335 + if (symbols == NULL) 334 336 return NULL; 335 337 336 - n = self->rb_node; 338 + n = symbols->rb_node; 337 339 338 340 while (n) { 339 341 struct symbol_name_rb_node *s; ··· 355 353 return NULL; 356 354 } 357 355 358 - struct symbol *dso__find_symbol(struct dso *self, 356 + struct symbol *dso__find_symbol(struct dso *dso, 359 357 enum map_type type, u64 addr) 360 358 { 361 - return symbols__find(&self->symbols[type], addr); 359 + return symbols__find(&dso->symbols[type], addr); 362 360 } 363 361 364 - struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, 362 + struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 365 363 const char *name) 366 364 { 367 - return symbols__find_by_name(&self->symbol_names[type], name); 365 + return symbols__find_by_name(&dso->symbol_names[type], name); 368 366 } 369 367 370 - void dso__sort_by_name(struct dso *self, enum map_type type) 368 + void dso__sort_by_name(struct dso *dso, enum map_type type) 371 369 { 372 - dso__set_sorted_by_name(self, type); 373 - return symbols__sort_by_name(&self->symbol_names[type], 374 - &self->symbols[type]); 370 + dso__set_sorted_by_name(dso, type); 371 + return symbols__sort_by_name(&dso->symbol_names[type], 372 + &dso->symbols[type]); 375 373 } 376 374 377 - int build_id__sprintf(const u8 *self, int len, char *bf) 375 + int build_id__sprintf(const u8 *build_id, int len, char *bf) 378 376 { 379 377 char *bid = bf; 380 - const u8 *raw = self; 378 + const u8 *raw = build_id; 381 379 int i; 382 380 383 381 for (i = 0; i < len; ++i) { ··· 386 384 bid += 2; 387 385 } 388 386 389 - return raw - self; 387 + return raw - build_id; 390 388 } 391 389 392 - size_t dso__fprintf_buildid(struct dso *self, FILE *fp) 390 + size_t dso__fprintf_buildid(struct dso *dso, FILE *fp) 393 391 { 394 392 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 395 393 396 - build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id); 394 + build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 397 395 return fprintf(fp, "%s", sbuild_id); 398 396 } 399 397 400 - size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp) 398 + size_t dso__fprintf_symbols_by_name(struct dso *dso, 399 + enum map_type type, FILE *fp) 401 400 { 402 401 size_t ret = 0; 403 402 struct rb_node *nd; 404 403 struct symbol_name_rb_node *pos; 405 404 406 - for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) { 405 + for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { 407 406 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); 408 407 fprintf(fp, "%s\n", pos->sym.name); 409 408 } ··· 412 409 return ret; 413 410 } 414 411 415 - size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp) 412 + size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) 416 413 { 417 414 struct rb_node *nd; 418 - size_t ret = fprintf(fp, "dso: %s (", self->short_name); 415 + size_t ret = fprintf(fp, "dso: %s (", dso->short_name); 419 416 420 - if (self->short_name != self->long_name) 421 - ret += fprintf(fp, "%s, ", self->long_name); 417 + if (dso->short_name != dso->long_name) 418 + ret += fprintf(fp, "%s, ", dso->long_name); 422 419 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type], 423 - self->loaded ? "" : "NOT "); 424 - ret += dso__fprintf_buildid(self, fp); 420 + dso->loaded ? "" : "NOT "); 421 + ret += dso__fprintf_buildid(dso, fp); 425 422 ret += fprintf(fp, ")\n"); 426 - for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) { 423 + for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) { 427 424 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 428 425 ret += symbol__fprintf(pos, fp); 429 426 } ··· 546 543 * so that we can in the next step set the symbol ->end address and then 547 544 * call kernel_maps__split_kallsyms. 548 545 */ 549 - static int dso__load_all_kallsyms(struct dso *self, const char *filename, 546 + static int dso__load_all_kallsyms(struct dso *dso, const char *filename, 550 547 struct map *map) 551 548 { 552 - struct process_kallsyms_args args = { .map = map, .dso = self, }; 549 + struct process_kallsyms_args args = { .map = map, .dso = dso, }; 553 550 return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 554 551 } 555 552 ··· 558 555 * kernel range is broken in several maps, named [kernel].N, as we don't have 559 556 * the original ELF section names vmlinux have. 560 557 */ 561 - static int dso__split_kallsyms(struct dso *self, struct map *map, 558 + static int dso__split_kallsyms(struct dso *dso, struct map *map, 562 559 symbol_filter_t filter) 563 560 { 564 561 struct map_groups *kmaps = map__kmap(map)->kmaps; ··· 566 563 struct map *curr_map = map; 567 564 struct symbol *pos; 568 565 int count = 0, moved = 0; 569 - struct rb_root *root = &self->symbols[map->type]; 566 + struct rb_root *root = &dso->symbols[map->type]; 570 567 struct rb_node *next = rb_first(root); 571 568 int kernel_range = 0; 572 569 ··· 585 582 586 583 if (strcmp(curr_map->dso->short_name, module)) { 587 584 if (curr_map != map && 588 - self->kernel == DSO_TYPE_GUEST_KERNEL && 585 + dso->kernel == DSO_TYPE_GUEST_KERNEL && 589 586 machine__is_default_guest(machine)) { 590 587 /* 591 588 * We assume all symbols of a module are ··· 621 618 pos->end = curr_map->map_ip(curr_map, pos->end); 622 619 } else if (curr_map != map) { 623 620 char dso_name[PATH_MAX]; 624 - struct dso *dso; 621 + struct dso *ndso; 625 622 626 623 if (count == 0) { 627 624 curr_map = map; 628 625 goto filter_symbol; 629 626 } 630 627 631 - if (self->kernel == DSO_TYPE_GUEST_KERNEL) 628 + if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 632 629 snprintf(dso_name, sizeof(dso_name), 633 630 "[guest.kernel].%d", 634 631 kernel_range++); ··· 637 634 "[kernel].%d", 638 635 kernel_range++); 639 636 640 - dso = dso__new(dso_name); 641 - if (dso == NULL) 637 + ndso = dso__new(dso_name); 638 + if (ndso == NULL) 642 639 return -1; 643 640 644 - dso->kernel = self->kernel; 641 + ndso->kernel = dso->kernel; 645 642 646 - curr_map = map__new2(pos->start, dso, map->type); 643 + curr_map = map__new2(pos->start, ndso, map->type); 647 644 if (curr_map == NULL) { 648 - dso__delete(dso); 645 + dso__delete(ndso); 649 646 return -1; 650 647 } 651 648 ··· 668 665 } 669 666 670 667 if (curr_map != map && 671 - self->kernel == DSO_TYPE_GUEST_KERNEL && 668 + dso->kernel == DSO_TYPE_GUEST_KERNEL && 672 669 machine__is_default_guest(kmaps->machine)) { 673 670 dso__set_loaded(curr_map->dso, curr_map->type); 674 671 } ··· 676 673 return count + moved; 677 674 } 678 675 679 - int dso__load_kallsyms(struct dso *self, const char *filename, 676 + int dso__load_kallsyms(struct dso *dso, const char *filename, 680 677 struct map *map, symbol_filter_t filter) 681 678 { 682 - if (dso__load_all_kallsyms(self, filename, map) < 0) 679 + if (dso__load_all_kallsyms(dso, filename, map) < 0) 683 680 return -1; 684 681 685 - if (self->kernel == DSO_TYPE_GUEST_KERNEL) 686 - self->symtab_type = SYMTAB__GUEST_KALLSYMS; 682 + if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 683 + dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 687 684 else 688 - self->symtab_type = SYMTAB__KALLSYMS; 685 + dso->symtab_type = SYMTAB__KALLSYMS; 689 686 690 - return dso__split_kallsyms(self, map, filter); 687 + return dso__split_kallsyms(dso, map, filter); 691 688 } 692 689 693 - static int dso__load_perf_map(struct dso *self, struct map *map, 690 + static int dso__load_perf_map(struct dso *dso, struct map *map, 694 691 symbol_filter_t filter) 695 692 { 696 693 char *line = NULL; ··· 698 695 FILE *file; 699 696 int nr_syms = 0; 700 697 701 - file = fopen(self->long_name, "r"); 698 + file = fopen(dso->long_name, "r"); 702 699 if (file == NULL) 703 700 goto out_failure; 704 701 ··· 736 733 if (filter && filter(map, sym)) 737 734 symbol__delete(sym); 738 735 else { 739 - symbols__insert(&self->symbols[map->type], sym); 736 + symbols__insert(&dso->symbols[map->type], sym); 740 737 nr_syms++; 741 738 } 742 739 } ··· 755 752 /** 756 753 * elf_symtab__for_each_symbol - iterate thru all the symbols 757 754 * 758 - * @self: struct elf_symtab instance to iterate 755 + * @syms: struct elf_symtab instance to iterate 759 756 * @idx: uint32_t idx 760 757 * @sym: GElf_Sym iterator 761 758 */ ··· 855 852 * And always look at the original dso, not at debuginfo packages, that 856 853 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 857 854 */ 858 - static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, 855 + static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, 859 856 symbol_filter_t filter) 860 857 { 861 858 uint32_t nr_rel_entries, idx; ··· 874 871 char name[PATH_MAX]; 875 872 876 873 snprintf(name, sizeof(name), "%s%s", 877 - symbol_conf.symfs, self->long_name); 874 + symbol_conf.symfs, dso->long_name); 878 875 fd = open(name, O_RDONLY); 879 876 if (fd < 0) 880 877 goto out; ··· 950 947 if (filter && filter(map, f)) 951 948 symbol__delete(f); 952 949 else { 953 - symbols__insert(&self->symbols[map->type], f); 950 + symbols__insert(&dso->symbols[map->type], f); 954 951 ++nr; 955 952 } 956 953 } ··· 972 969 if (filter && filter(map, f)) 973 970 symbol__delete(f); 974 971 else { 975 - symbols__insert(&self->symbols[map->type], f); 972 + symbols__insert(&dso->symbols[map->type], f); 976 973 ++nr; 977 974 } 978 975 } ··· 988 985 return nr; 989 986 out: 990 987 pr_debug("%s: problems reading %s PLT info.\n", 991 - __func__, self->long_name); 988 + __func__, dso->long_name); 992 989 return 0; 993 990 } 994 991 995 - static bool elf_sym__is_a(GElf_Sym *self, enum map_type type) 992 + static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) 996 993 { 997 994 switch (type) { 998 995 case MAP__FUNCTION: 999 - return elf_sym__is_function(self); 996 + return elf_sym__is_function(sym); 1000 997 case MAP__VARIABLE: 1001 - return elf_sym__is_object(self); 998 + return elf_sym__is_object(sym); 1002 999 default: 1003 1000 return false; 1004 1001 } 1005 1002 } 1006 1003 1007 - static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type) 1004 + static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, 1005 + enum map_type type) 1008 1006 { 1009 1007 switch (type) { 1010 1008 case MAP__FUNCTION: 1011 - return elf_sec__is_text(self, secstrs); 1009 + return elf_sec__is_text(shdr, secstrs); 1012 1010 case MAP__VARIABLE: 1013 - return elf_sec__is_data(self, secstrs); 1011 + return elf_sec__is_data(shdr, secstrs); 1014 1012 default: 1015 1013 return false; 1016 1014 } ··· 1036 1032 return -1; 1037 1033 } 1038 1034 1039 - static int dso__load_sym(struct dso *self, struct map *map, const char *name, 1035 + static int dso__load_sym(struct dso *dso, struct map *map, const char *name, 1040 1036 int fd, symbol_filter_t filter, int kmodule, 1041 1037 int want_symtab) 1042 1038 { 1043 - struct kmap *kmap = self->kernel ? map__kmap(map) : NULL; 1039 + struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 1044 1040 struct map *curr_map = map; 1045 - struct dso *curr_dso = self; 1041 + struct dso *curr_dso = dso; 1046 1042 Elf_Data *symstrs, *secstrs; 1047 1043 uint32_t nr_syms; 1048 1044 int err = -1; ··· 1068 1064 } 1069 1065 1070 1066 /* Always reject images with a mismatched build-id: */ 1071 - if (self->has_build_id) { 1067 + if (dso->has_build_id) { 1072 1068 u8 build_id[BUILD_ID_SIZE]; 1073 1069 1074 1070 if (elf_read_build_id(elf, build_id, 1075 1071 BUILD_ID_SIZE) != BUILD_ID_SIZE) 1076 1072 goto out_elf_end; 1077 1073 1078 - if (!dso__build_id_equal(self, build_id)) 1074 + if (!dso__build_id_equal(dso, build_id)) 1079 1075 goto out_elf_end; 1080 1076 } 1081 1077 ··· 1116 1112 nr_syms = shdr.sh_size / shdr.sh_entsize; 1117 1113 1118 1114 memset(&sym, 0, sizeof(sym)); 1119 - if (self->kernel == DSO_TYPE_USER) { 1120 - self->adjust_symbols = (ehdr.e_type == ET_EXEC || 1115 + if (dso->kernel == DSO_TYPE_USER) { 1116 + dso->adjust_symbols = (ehdr.e_type == ET_EXEC || 1121 1117 elf_section_by_name(elf, &ehdr, &shdr, 1122 1118 ".gnu.prelink_undo", 1123 1119 NULL) != NULL); 1124 - } else self->adjust_symbols = 0; 1125 - 1120 + } else { 1121 + dso->adjust_symbols = 0; 1122 + } 1126 1123 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 1127 1124 struct symbol *f; 1128 1125 const char *elf_name = elf_sym__name(&sym, symstrs); ··· 1173 1168 (sym.st_value & 1)) 1174 1169 --sym.st_value; 1175 1170 1176 - if (self->kernel != DSO_TYPE_USER || kmodule) { 1171 + if (dso->kernel != DSO_TYPE_USER || kmodule) { 1177 1172 char dso_name[PATH_MAX]; 1178 1173 1179 1174 if (strcmp(section_name, 1180 1175 (curr_dso->short_name + 1181 - self->short_name_len)) == 0) 1176 + dso->short_name_len)) == 0) 1182 1177 goto new_symbol; 1183 1178 1184 1179 if (strcmp(section_name, ".text") == 0) { 1185 1180 curr_map = map; 1186 - curr_dso = self; 1181 + curr_dso = dso; 1187 1182 goto new_symbol; 1188 1183 } 1189 1184 1190 1185 snprintf(dso_name, sizeof(dso_name), 1191 - "%s%s", self->short_name, section_name); 1186 + "%s%s", dso->short_name, section_name); 1192 1187 1193 1188 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); 1194 1189 if (curr_map == NULL) { ··· 1200 1195 curr_dso = dso__new(dso_name); 1201 1196 if (curr_dso == NULL) 1202 1197 goto out_elf_end; 1203 - curr_dso->kernel = self->kernel; 1204 - curr_dso->long_name = self->long_name; 1205 - curr_dso->long_name_len = self->long_name_len; 1198 + curr_dso->kernel = dso->kernel; 1199 + curr_dso->long_name = dso->long_name; 1200 + curr_dso->long_name_len = dso->long_name_len; 1206 1201 curr_map = map__new2(start, curr_dso, 1207 1202 map->type); 1208 1203 if (curr_map == NULL) { ··· 1211 1206 } 1212 1207 curr_map->map_ip = identity__map_ip; 1213 1208 curr_map->unmap_ip = identity__map_ip; 1214 - curr_dso->symtab_type = self->symtab_type; 1209 + curr_dso->symtab_type = dso->symtab_type; 1215 1210 map_groups__insert(kmap->kmaps, curr_map); 1216 - dsos__add(&self->node, curr_dso); 1211 + dsos__add(&dso->node, curr_dso); 1217 1212 dso__set_loaded(curr_dso, map->type); 1218 1213 } else 1219 1214 curr_dso = curr_map->dso; ··· 1255 1250 * For misannotated, zeroed, ASM function sizes. 1256 1251 */ 1257 1252 if (nr > 0) { 1258 - symbols__fixup_end(&self->symbols[map->type]); 1253 + symbols__fixup_end(&dso->symbols[map->type]); 1259 1254 if (kmap) { 1260 1255 /* 1261 1256 * We need to fixup this here too because we create new ··· 1271 1266 return err; 1272 1267 } 1273 1268 1274 - static bool dso__build_id_equal(const struct dso *self, u8 *build_id) 1269 + static bool dso__build_id_equal(const struct dso *dso, u8 *build_id) 1275 1270 { 1276 - return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; 1271 + return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0; 1277 1272 } 1278 1273 1279 1274 bool __dsos__read_build_ids(struct list_head *head, bool with_hits) ··· 1434 1429 return err; 1435 1430 } 1436 1431 1437 - char dso__symtab_origin(const struct dso *self) 1432 + char dso__symtab_origin(const struct dso *dso) 1438 1433 { 1439 1434 static const char origin[] = { 1440 1435 [SYMTAB__KALLSYMS] = 'k', ··· 1449 1444 [SYMTAB__GUEST_KMODULE] = 'G', 1450 1445 }; 1451 1446 1452 - if (self == NULL || self->symtab_type == SYMTAB__NOT_FOUND) 1447 + if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND) 1453 1448 return '!'; 1454 - return origin[self->symtab_type]; 1449 + return origin[dso->symtab_type]; 1455 1450 } 1456 1451 1457 - int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) 1452 + int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1458 1453 { 1459 1454 int size = PATH_MAX; 1460 1455 char *name; ··· 1464 1459 const char *root_dir; 1465 1460 int want_symtab; 1466 1461 1467 - dso__set_loaded(self, map->type); 1462 + dso__set_loaded(dso, map->type); 1468 1463 1469 - if (self->kernel == DSO_TYPE_KERNEL) 1470 - return dso__load_kernel_sym(self, map, filter); 1471 - else if (self->kernel == DSO_TYPE_GUEST_KERNEL) 1472 - return dso__load_guest_kernel_sym(self, map, filter); 1464 + if (dso->kernel == DSO_TYPE_KERNEL) 1465 + return dso__load_kernel_sym(dso, map, filter); 1466 + else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1467 + return dso__load_guest_kernel_sym(dso, map, filter); 1473 1468 1474 1469 if (map->groups && map->groups->machine) 1475 1470 machine = map->groups->machine; ··· 1480 1475 if (!name) 1481 1476 return -1; 1482 1477 1483 - self->adjust_symbols = 0; 1478 + dso->adjust_symbols = 0; 1484 1479 1485 - if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 1486 - ret = dso__load_perf_map(self, map, filter); 1487 - self->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1480 + if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1481 + ret = dso__load_perf_map(dso, map, filter); 1482 + dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1488 1483 SYMTAB__NOT_FOUND; 1489 1484 return ret; 1490 1485 } ··· 1495 1490 */ 1496 1491 want_symtab = 1; 1497 1492 restart: 1498 - for (self->symtab_type = SYMTAB__BUILD_ID_CACHE; 1499 - self->symtab_type != SYMTAB__NOT_FOUND; 1500 - self->symtab_type++) { 1501 - switch (self->symtab_type) { 1493 + for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; 1494 + dso->symtab_type != SYMTAB__NOT_FOUND; 1495 + dso->symtab_type++) { 1496 + switch (dso->symtab_type) { 1502 1497 case SYMTAB__BUILD_ID_CACHE: 1503 1498 /* skip the locally configured cache if a symfs is given */ 1504 1499 if (symbol_conf.symfs[0] || 1505 - (dso__build_id_filename(self, name, size) == NULL)) { 1500 + (dso__build_id_filename(dso, name, size) == NULL)) { 1506 1501 continue; 1507 1502 } 1508 1503 break; 1509 1504 case SYMTAB__FEDORA_DEBUGINFO: 1510 1505 snprintf(name, size, "%s/usr/lib/debug%s.debug", 1511 - symbol_conf.symfs, self->long_name); 1506 + symbol_conf.symfs, dso->long_name); 1512 1507 break; 1513 1508 case SYMTAB__UBUNTU_DEBUGINFO: 1514 1509 snprintf(name, size, "%s/usr/lib/debug%s", 1515 - symbol_conf.symfs, self->long_name); 1510 + symbol_conf.symfs, dso->long_name); 1516 1511 break; 1517 1512 case SYMTAB__BUILDID_DEBUGINFO: { 1518 1513 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1519 1514 1520 - if (!self->has_build_id) 1515 + if (!dso->has_build_id) 1521 1516 continue; 1522 1517 1523 - build_id__sprintf(self->build_id, 1524 - sizeof(self->build_id), 1518 + build_id__sprintf(dso->build_id, 1519 + sizeof(dso->build_id), 1525 1520 build_id_hex); 1526 1521 snprintf(name, size, 1527 1522 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", ··· 1530 1525 break; 1531 1526 case SYMTAB__SYSTEM_PATH_DSO: 1532 1527 snprintf(name, size, "%s%s", 1533 - symbol_conf.symfs, self->long_name); 1528 + symbol_conf.symfs, dso->long_name); 1534 1529 break; 1535 1530 case SYMTAB__GUEST_KMODULE: 1536 1531 if (map->groups && machine) ··· 1538 1533 else 1539 1534 root_dir = ""; 1540 1535 snprintf(name, size, "%s%s%s", symbol_conf.symfs, 1541 - root_dir, self->long_name); 1536 + root_dir, dso->long_name); 1542 1537 break; 1543 1538 1544 1539 case SYMTAB__SYSTEM_PATH_KMODULE: 1545 1540 snprintf(name, size, "%s%s", symbol_conf.symfs, 1546 - self->long_name); 1541 + dso->long_name); 1547 1542 break; 1548 1543 default:; 1549 1544 } ··· 1553 1548 if (fd < 0) 1554 1549 continue; 1555 1550 1556 - ret = dso__load_sym(self, map, name, fd, filter, 0, 1551 + ret = dso__load_sym(dso, map, name, fd, filter, 0, 1557 1552 want_symtab); 1558 1553 close(fd); 1559 1554 ··· 1565 1560 continue; 1566 1561 1567 1562 if (ret > 0) { 1568 - int nr_plt = dso__synthesize_plt_symbols(self, map, filter); 1563 + int nr_plt = dso__synthesize_plt_symbols(dso, map, 1564 + filter); 1569 1565 if (nr_plt > 0) 1570 1566 ret += nr_plt; 1571 1567 break; ··· 1583 1577 } 1584 1578 1585 1579 free(name); 1586 - if (ret < 0 && strstr(self->name, " (deleted)") != NULL) 1580 + if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) 1587 1581 return 0; 1588 1582 return ret; 1589 1583 } 1590 1584 1591 - struct map *map_groups__find_by_name(struct map_groups *self, 1585 + struct map *map_groups__find_by_name(struct map_groups *mg, 1592 1586 enum map_type type, const char *name) 1593 1587 { 1594 1588 struct rb_node *nd; 1595 1589 1596 - for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { 1590 + for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 1597 1591 struct map *map = rb_entry(nd, struct map, rb_node); 1598 1592 1599 1593 if (map->dso && strcmp(map->dso->short_name, name) == 0) ··· 1603 1597 return NULL; 1604 1598 } 1605 1599 1606 - static int dso__kernel_module_get_build_id(struct dso *self, 1607 - const char *root_dir) 1600 + static int dso__kernel_module_get_build_id(struct dso *dso, 1601 + const char *root_dir) 1608 1602 { 1609 1603 char filename[PATH_MAX]; 1610 1604 /* 1611 1605 * kernel module short names are of the form "[module]" and 1612 1606 * we need just "module" here. 1613 1607 */ 1614 - const char *name = self->short_name + 1; 1608 + const char *name = dso->short_name + 1; 1615 1609 1616 1610 snprintf(filename, sizeof(filename), 1617 1611 "%s/sys/module/%.*s/notes/.note.gnu.build-id", 1618 1612 root_dir, (int)strlen(name) - 1, name); 1619 1613 1620 - if (sysfs__read_build_id(filename, self->build_id, 1621 - sizeof(self->build_id)) == 0) 1622 - self->has_build_id = true; 1614 + if (sysfs__read_build_id(filename, dso->build_id, 1615 + sizeof(dso->build_id)) == 0) 1616 + dso->has_build_id = true; 1623 1617 1624 1618 return 0; 1625 1619 } 1626 1620 1627 - static int map_groups__set_modules_path_dir(struct map_groups *self, 1621 + static int map_groups__set_modules_path_dir(struct map_groups *mg, 1628 1622 const char *dir_name) 1629 1623 { 1630 1624 struct dirent *dent; ··· 1652 1646 1653 1647 snprintf(path, sizeof(path), "%s/%s", 1654 1648 dir_name, dent->d_name); 1655 - ret = map_groups__set_modules_path_dir(self, path); 1649 + ret = map_groups__set_modules_path_dir(mg, path); 1656 1650 if (ret < 0) 1657 1651 goto out; 1658 1652 } else { ··· 1667 1661 (int)(dot - dent->d_name), dent->d_name); 1668 1662 1669 1663 strxfrchar(dso_name, '-', '_'); 1670 - map = map_groups__find_by_name(self, MAP__FUNCTION, dso_name); 1664 + map = map_groups__find_by_name(mg, MAP__FUNCTION, 1665 + dso_name); 1671 1666 if (map == NULL) 1672 1667 continue; 1673 1668 ··· 1718 1711 return strdup(name); 1719 1712 } 1720 1713 1721 - static int machine__set_modules_path(struct machine *self) 1714 + static int machine__set_modules_path(struct machine *machine) 1722 1715 { 1723 1716 char *version; 1724 1717 char modules_path[PATH_MAX]; 1725 1718 1726 - version = get_kernel_version(self->root_dir); 1719 + version = get_kernel_version(machine->root_dir); 1727 1720 if (!version) 1728 1721 return -1; 1729 1722 1730 1723 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", 1731 - self->root_dir, version); 1724 + machine->root_dir, version); 1732 1725 free(version); 1733 1726 1734 - return map_groups__set_modules_path_dir(&self->kmaps, modules_path); 1727 + return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 1735 1728 } 1736 1729 1737 1730 /* ··· 1741 1734 */ 1742 1735 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) 1743 1736 { 1744 - struct map *self = calloc(1, (sizeof(*self) + 1745 - (dso->kernel ? sizeof(struct kmap) : 0))); 1746 - if (self != NULL) { 1737 + struct map *map = calloc(1, (sizeof(*map) + 1738 + (dso->kernel ? sizeof(struct kmap) : 0))); 1739 + if (map != NULL) { 1747 1740 /* 1748 1741 * ->end will be filled after we load all the symbols 1749 1742 */ 1750 - map__init(self, type, start, 0, 0, dso); 1743 + map__init(map, type, start, 0, 0, dso); 1751 1744 } 1752 1745 1753 - return self; 1746 + return map; 1754 1747 } 1755 1748 1756 - struct map *machine__new_module(struct machine *self, u64 start, 1749 + struct map *machine__new_module(struct machine *machine, u64 start, 1757 1750 const char *filename) 1758 1751 { 1759 1752 struct map *map; 1760 - struct dso *dso = __dsos__findnew(&self->kernel_dsos, filename); 1753 + struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 1761 1754 1762 1755 if (dso == NULL) 1763 1756 return NULL; ··· 1766 1759 if (map == NULL) 1767 1760 return NULL; 1768 1761 1769 - if (machine__is_host(self)) 1762 + if (machine__is_host(machine)) 1770 1763 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; 1771 1764 else 1772 1765 dso->symtab_type = SYMTAB__GUEST_KMODULE; 1773 - map_groups__insert(&self->kmaps, map); 1766 + map_groups__insert(&machine->kmaps, map); 1774 1767 return map; 1775 1768 } 1776 1769 1777 - static int machine__create_modules(struct machine *self) 1770 + static int machine__create_modules(struct machine *machine) 1778 1771 { 1779 1772 char *line = NULL; 1780 1773 size_t n; ··· 1783 1776 const char *modules; 1784 1777 char path[PATH_MAX]; 1785 1778 1786 - if (machine__is_default_guest(self)) 1779 + if (machine__is_default_guest(machine)) 1787 1780 modules = symbol_conf.default_guest_modules; 1788 1781 else { 1789 - sprintf(path, "%s/proc/modules", self->root_dir); 1782 + sprintf(path, "%s/proc/modules", machine->root_dir); 1790 1783 modules = path; 1791 1784 } 1792 1785 ··· 1822 1815 *sep = '\0'; 1823 1816 1824 1817 snprintf(name, sizeof(name), "[%s]", line); 1825 - map = machine__new_module(self, start, name); 1818 + map = machine__new_module(machine, start, name); 1826 1819 if (map == NULL) 1827 1820 goto out_delete_line; 1828 - dso__kernel_module_get_build_id(map->dso, self->root_dir); 1821 + dso__kernel_module_get_build_id(map->dso, machine->root_dir); 1829 1822 } 1830 1823 1831 1824 free(line); 1832 1825 fclose(file); 1833 1826 1834 - return machine__set_modules_path(self); 1827 + return machine__set_modules_path(machine); 1835 1828 1836 1829 out_delete_line: 1837 1830 free(line); ··· 1839 1832 return -1; 1840 1833 } 1841 1834 1842 - int dso__load_vmlinux(struct dso *self, struct map *map, 1835 + int dso__load_vmlinux(struct dso *dso, struct map *map, 1843 1836 const char *vmlinux, symbol_filter_t filter) 1844 1837 { 1845 1838 int err = -1, fd; ··· 1851 1844 if (fd < 0) 1852 1845 return -1; 1853 1846 1854 - dso__set_long_name(self, (char *)vmlinux); 1855 - dso__set_loaded(self, map->type); 1856 - err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); 1847 + dso__set_long_name(dso, (char *)vmlinux); 1848 + dso__set_loaded(dso, map->type); 1849 + err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0); 1857 1850 close(fd); 1858 1851 1859 1852 if (err > 0) ··· 1862 1855 return err; 1863 1856 } 1864 1857 1865 - int dso__load_vmlinux_path(struct dso *self, struct map *map, 1858 + int dso__load_vmlinux_path(struct dso *dso, struct map *map, 1866 1859 symbol_filter_t filter) 1867 1860 { 1868 1861 int i, err = 0; ··· 1871 1864 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1872 1865 vmlinux_path__nr_entries + 1); 1873 1866 1874 - filename = dso__build_id_filename(self, NULL, 0); 1867 + filename = dso__build_id_filename(dso, NULL, 0); 1875 1868 if (filename != NULL) { 1876 - err = dso__load_vmlinux(self, map, filename, filter); 1869 + err = dso__load_vmlinux(dso, map, filename, filter); 1877 1870 if (err > 0) { 1878 - dso__set_long_name(self, filename); 1871 + dso__set_long_name(dso, filename); 1879 1872 goto out; 1880 1873 } 1881 1874 free(filename); 1882 1875 } 1883 1876 1884 1877 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1885 - err = dso__load_vmlinux(self, map, vmlinux_path[i], filter); 1878 + err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); 1886 1879 if (err > 0) { 1887 - dso__set_long_name(self, strdup(vmlinux_path[i])); 1880 + dso__set_long_name(dso, strdup(vmlinux_path[i])); 1888 1881 break; 1889 1882 } 1890 1883 } ··· 1892 1885 return err; 1893 1886 } 1894 1887 1895 - static int dso__load_kernel_sym(struct dso *self, struct map *map, 1888 + static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1896 1889 symbol_filter_t filter) 1897 1890 { 1898 1891 int err; ··· 1919 1912 } 1920 1913 1921 1914 if (symbol_conf.vmlinux_name != NULL) { 1922 - err = dso__load_vmlinux(self, map, 1915 + err = dso__load_vmlinux(dso, map, 1923 1916 symbol_conf.vmlinux_name, filter); 1924 1917 if (err > 0) { 1925 - dso__set_long_name(self, 1918 + dso__set_long_name(dso, 1926 1919 strdup(symbol_conf.vmlinux_name)); 1927 1920 goto out_fixup; 1928 1921 } ··· 1930 1923 } 1931 1924 1932 1925 if (vmlinux_path != NULL) { 1933 - err = dso__load_vmlinux_path(self, map, filter); 1926 + err = dso__load_vmlinux_path(dso, map, filter); 1934 1927 if (err > 0) 1935 1928 goto out_fixup; 1936 1929 } ··· 1944 1937 * we have a build-id, so check if it is the same as the running kernel, 1945 1938 * using it if it is. 1946 1939 */ 1947 - if (self->has_build_id) { 1940 + if (dso->has_build_id) { 1948 1941 u8 kallsyms_build_id[BUILD_ID_SIZE]; 1949 1942 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1950 1943 1951 1944 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id, 1952 1945 sizeof(kallsyms_build_id)) == 0) { 1953 - if (dso__build_id_equal(self, kallsyms_build_id)) { 1946 + if (dso__build_id_equal(dso, kallsyms_build_id)) { 1954 1947 kallsyms_filename = "/proc/kallsyms"; 1955 1948 goto do_kallsyms; 1956 1949 } ··· 1959 1952 * Now look if we have it on the build-id cache in 1960 1953 * $HOME/.debug/[kernel.kallsyms]. 1961 1954 */ 1962 - build_id__sprintf(self->build_id, sizeof(self->build_id), 1955 + build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1963 1956 sbuild_id); 1964 1957 1965 1958 if (asprintf(&kallsyms_allocated_filename, ··· 1986 1979 } 1987 1980 1988 1981 do_kallsyms: 1989 - err = dso__load_kallsyms(self, kallsyms_filename, map, filter); 1982 + err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1990 1983 if (err > 0) 1991 1984 pr_debug("Using %s for symbols\n", kallsyms_filename); 1992 1985 free(kallsyms_allocated_filename); ··· 1994 1987 if (err > 0) { 1995 1988 out_fixup: 1996 1989 if (kallsyms_filename != NULL) 1997 - dso__set_long_name(self, strdup("[kernel.kallsyms]")); 1990 + dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 1998 1991 map__fixup_start(map); 1999 1992 map__fixup_end(map); 2000 1993 } ··· 2002 1995 return err; 2003 1996 } 2004 1997 2005 - static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, 2006 - symbol_filter_t filter) 1998 + static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 1999 + symbol_filter_t filter) 2007 2000 { 2008 2001 int err; 2009 2002 const char *kallsyms_filename = NULL; ··· 2023 2016 * Or use file guest_kallsyms inputted by user on commandline 2024 2017 */ 2025 2018 if (symbol_conf.default_guest_vmlinux_name != NULL) { 2026 - err = dso__load_vmlinux(self, map, 2019 + err = dso__load_vmlinux(dso, map, 2027 2020 symbol_conf.default_guest_vmlinux_name, filter); 2028 2021 goto out_try_fixup; 2029 2022 } ··· 2036 2029 kallsyms_filename = path; 2037 2030 } 2038 2031 2039 - err = dso__load_kallsyms(self, kallsyms_filename, map, filter); 2032 + err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 2040 2033 if (err > 0) 2041 2034 pr_debug("Using %s for symbols\n", kallsyms_filename); 2042 2035 ··· 2044 2037 if (err > 0) { 2045 2038 if (kallsyms_filename != NULL) { 2046 2039 machine__mmap_name(machine, path, sizeof(path)); 2047 - dso__set_long_name(self, strdup(path)); 2040 + dso__set_long_name(dso, strdup(path)); 2048 2041 } 2049 2042 map__fixup_start(map); 2050 2043 map__fixup_end(map); ··· 2097 2090 return ret; 2098 2091 } 2099 2092 2100 - size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp) 2093 + size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) 2101 2094 { 2102 2095 struct rb_node *nd; 2103 2096 size_t ret = 0; 2104 2097 2105 - for (nd = rb_first(self); nd; nd = rb_next(nd)) { 2098 + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { 2106 2099 struct machine *pos = rb_entry(nd, struct machine, rb_node); 2107 2100 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 2108 2101 ret += __dsos__fprintf(&pos->user_dsos, fp); ··· 2126 2119 return ret; 2127 2120 } 2128 2121 2129 - size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits) 2122 + size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 2123 + bool with_hits) 2130 2124 { 2131 - return __dsos__fprintf_buildid(&self->kernel_dsos, fp, with_hits) + 2132 - __dsos__fprintf_buildid(&self->user_dsos, fp, with_hits); 2125 + return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) + 2126 + __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits); 2133 2127 } 2134 2128 2135 - size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits) 2129 + size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 2130 + FILE *fp, bool with_hits) 2136 2131 { 2137 2132 struct rb_node *nd; 2138 2133 size_t ret = 0; 2139 2134 2140 - for (nd = rb_first(self); nd; nd = rb_next(nd)) { 2135 + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { 2141 2136 struct machine *pos = rb_entry(nd, struct machine, rb_node); 2142 2137 ret += machine__fprintf_dsos_buildid(pos, fp, with_hits); 2143 2138 } ··· 2148 2139 2149 2140 struct dso *dso__new_kernel(const char *name) 2150 2141 { 2151 - struct dso *self = dso__new(name ?: "[kernel.kallsyms]"); 2142 + struct dso *dso = dso__new(name ?: "[kernel.kallsyms]"); 2152 2143 2153 - if (self != NULL) { 2154 - dso__set_short_name(self, "[kernel]"); 2155 - self->kernel = DSO_TYPE_KERNEL; 2144 + if (dso != NULL) { 2145 + dso__set_short_name(dso, "[kernel]"); 2146 + dso->kernel = DSO_TYPE_KERNEL; 2156 2147 } 2157 2148 2158 - return self; 2149 + return dso; 2159 2150 } 2160 2151 2161 2152 static struct dso *dso__new_guest_kernel(struct machine *machine, 2162 2153 const char *name) 2163 2154 { 2164 2155 char bf[PATH_MAX]; 2165 - struct dso *self = dso__new(name ?: machine__mmap_name(machine, bf, sizeof(bf))); 2166 - 2167 - if (self != NULL) { 2168 - dso__set_short_name(self, "[guest.kernel]"); 2169 - self->kernel = DSO_TYPE_GUEST_KERNEL; 2156 + struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf, 2157 + sizeof(bf))); 2158 + if (dso != NULL) { 2159 + dso__set_short_name(dso, "[guest.kernel]"); 2160 + dso->kernel = DSO_TYPE_GUEST_KERNEL; 2170 2161 } 2171 2162 2172 - return self; 2163 + return dso; 2173 2164 } 2174 2165 2175 - void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine) 2166 + void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine) 2176 2167 { 2177 2168 char path[PATH_MAX]; 2178 2169 2179 2170 if (machine__is_default_guest(machine)) 2180 2171 return; 2181 2172 sprintf(path, "%s/sys/kernel/notes", machine->root_dir); 2182 - if (sysfs__read_build_id(path, self->build_id, 2183 - sizeof(self->build_id)) == 0) 2184 - self->has_build_id = true; 2173 + if (sysfs__read_build_id(path, dso->build_id, 2174 + sizeof(dso->build_id)) == 0) 2175 + dso->has_build_id = true; 2185 2176 } 2186 2177 2187 - static struct dso *machine__create_kernel(struct machine *self) 2178 + static struct dso *machine__create_kernel(struct machine *machine) 2188 2179 { 2189 2180 const char *vmlinux_name = NULL; 2190 2181 struct dso *kernel; 2191 2182 2192 - if (machine__is_host(self)) { 2183 + if (machine__is_host(machine)) { 2193 2184 vmlinux_name = symbol_conf.vmlinux_name; 2194 2185 kernel = dso__new_kernel(vmlinux_name); 2195 2186 } else { 2196 - if (machine__is_default_guest(self)) 2187 + if (machine__is_default_guest(machine)) 2197 2188 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 2198 - kernel = dso__new_guest_kernel(self, vmlinux_name); 2189 + kernel = dso__new_guest_kernel(machine, vmlinux_name); 2199 2190 } 2200 2191 2201 2192 if (kernel != NULL) { 2202 - dso__read_running_kernel_build_id(kernel, self); 2203 - dsos__add(&self->kernel_dsos, kernel); 2193 + dso__read_running_kernel_build_id(kernel, machine); 2194 + dsos__add(&machine->kernel_dsos, kernel); 2204 2195 } 2205 2196 return kernel; 2206 2197 } ··· 2245 2236 return args.start; 2246 2237 } 2247 2238 2248 - int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) 2239 + int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 2249 2240 { 2250 2241 enum map_type type; 2251 - u64 start = machine__get_kernel_start_addr(self); 2242 + u64 start = machine__get_kernel_start_addr(machine); 2252 2243 2253 2244 for (type = 0; type < MAP__NR_TYPES; ++type) { 2254 2245 struct kmap *kmap; 2255 2246 2256 - self->vmlinux_maps[type] = map__new2(start, kernel, type); 2257 - if (self->vmlinux_maps[type] == NULL) 2247 + machine->vmlinux_maps[type] = map__new2(start, kernel, type); 2248 + if (machine->vmlinux_maps[type] == NULL) 2258 2249 return -1; 2259 2250 2260 - self->vmlinux_maps[type]->map_ip = 2261 - self->vmlinux_maps[type]->unmap_ip = identity__map_ip; 2262 - 2263 - kmap = map__kmap(self->vmlinux_maps[type]); 2264 - kmap->kmaps = &self->kmaps; 2265 - map_groups__insert(&self->kmaps, self->vmlinux_maps[type]); 2251 + machine->vmlinux_maps[type]->map_ip = 2252 + machine->vmlinux_maps[type]->unmap_ip = 2253 + identity__map_ip; 2254 + kmap = map__kmap(machine->vmlinux_maps[type]); 2255 + kmap->kmaps = &machine->kmaps; 2256 + map_groups__insert(&machine->kmaps, 2257 + machine->vmlinux_maps[type]); 2266 2258 } 2267 2259 2268 2260 return 0; 2269 2261 } 2270 2262 2271 - void machine__destroy_kernel_maps(struct machine *self) 2263 + void machine__destroy_kernel_maps(struct machine *machine) 2272 2264 { 2273 2265 enum map_type type; 2274 2266 2275 2267 for (type = 0; type < MAP__NR_TYPES; ++type) { 2276 2268 struct kmap *kmap; 2277 2269 2278 - if (self->vmlinux_maps[type] == NULL) 2270 + if (machine->vmlinux_maps[type] == NULL) 2279 2271 continue; 2280 2272 2281 - kmap = map__kmap(self->vmlinux_maps[type]); 2282 - map_groups__remove(&self->kmaps, self->vmlinux_maps[type]); 2273 + kmap = map__kmap(machine->vmlinux_maps[type]); 2274 + map_groups__remove(&machine->kmaps, 2275 + machine->vmlinux_maps[type]); 2283 2276 if (kmap->ref_reloc_sym) { 2284 2277 /* 2285 2278 * ref_reloc_sym is shared among all maps, so free just ··· 2295 2284 kmap->ref_reloc_sym = NULL; 2296 2285 } 2297 2286 2298 - map__delete(self->vmlinux_maps[type]); 2299 - self->vmlinux_maps[type] = NULL; 2287 + map__delete(machine->vmlinux_maps[type]); 2288 + machine->vmlinux_maps[type] = NULL; 2300 2289 } 2301 2290 } 2302 2291 2303 - int machine__create_kernel_maps(struct machine *self) 2292 + int machine__create_kernel_maps(struct machine *machine) 2304 2293 { 2305 - struct dso *kernel = machine__create_kernel(self); 2294 + struct dso *kernel = machine__create_kernel(machine); 2306 2295 2307 2296 if (kernel == NULL || 2308 - __machine__create_kernel_maps(self, kernel) < 0) 2297 + __machine__create_kernel_maps(machine, kernel) < 0) 2309 2298 return -1; 2310 2299 2311 - if (symbol_conf.use_modules && machine__create_modules(self) < 0) 2300 + if (symbol_conf.use_modules && machine__create_modules(machine) < 0) 2312 2301 pr_debug("Problems creating module maps, continuing anyway...\n"); 2313 2302 /* 2314 2303 * Now that we have all the maps created, just set the ->end of them: 2315 2304 */ 2316 - map_groups__fixup_end(&self->kmaps); 2305 + map_groups__fixup_end(&machine->kmaps); 2317 2306 return 0; 2318 2307 } 2319 2308 ··· 2377 2366 return -1; 2378 2367 } 2379 2368 2380 - size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp) 2369 + size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) 2381 2370 { 2382 2371 int i; 2383 2372 size_t printed = 0; 2384 - struct dso *kdso = self->vmlinux_maps[MAP__FUNCTION]->dso; 2373 + struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; 2385 2374 2386 2375 if (kdso->has_build_id) { 2387 2376 char filename[PATH_MAX]; ··· 2478 2467 symbol_conf.initialized = false; 2479 2468 } 2480 2469 2481 - int machines__create_kernel_maps(struct rb_root *self, pid_t pid) 2470 + int machines__create_kernel_maps(struct rb_root *machines, pid_t pid) 2482 2471 { 2483 - struct machine *machine = machines__findnew(self, pid); 2472 + struct machine *machine = machines__findnew(machines, pid); 2484 2473 2485 2474 if (machine == NULL) 2486 2475 return -1; ··· 2531 2520 return s; 2532 2521 } 2533 2522 2534 - int machines__create_guest_kernel_maps(struct rb_root *self) 2523 + int machines__create_guest_kernel_maps(struct rb_root *machines) 2535 2524 { 2536 2525 int ret = 0; 2537 2526 struct dirent **namelist = NULL; ··· 2542 2531 if (symbol_conf.default_guest_vmlinux_name || 2543 2532 symbol_conf.default_guest_modules || 2544 2533 symbol_conf.default_guest_kallsyms) { 2545 - machines__create_kernel_maps(self, DEFAULT_GUEST_KERNEL_ID); 2534 + machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); 2546 2535 } 2547 2536 2548 2537 if (symbol_conf.guestmount) { ··· 2563 2552 pr_debug("Can't access file %s\n", path); 2564 2553 goto failure; 2565 2554 } 2566 - machines__create_kernel_maps(self, pid); 2555 + machines__create_kernel_maps(machines, pid); 2567 2556 } 2568 2557 failure: 2569 2558 free(namelist); ··· 2572 2561 return ret; 2573 2562 } 2574 2563 2575 - void machines__destroy_guest_kernel_maps(struct rb_root *self) 2564 + void machines__destroy_guest_kernel_maps(struct rb_root *machines) 2576 2565 { 2577 - struct rb_node *next = rb_first(self); 2566 + struct rb_node *next = rb_first(machines); 2578 2567 2579 2568 while (next) { 2580 2569 struct machine *pos = rb_entry(next, struct machine, rb_node); 2581 2570 2582 2571 next = rb_next(&pos->rb_node); 2583 - rb_erase(&pos->rb_node, self); 2572 + rb_erase(&pos->rb_node, machines); 2584 2573 machine__delete(pos); 2585 2574 } 2586 2575 } 2587 2576 2588 - int machine__load_kallsyms(struct machine *self, const char *filename, 2577 + int machine__load_kallsyms(struct machine *machine, const char *filename, 2589 2578 enum map_type type, symbol_filter_t filter) 2590 2579 { 2591 - struct map *map = self->vmlinux_maps[type]; 2580 + struct map *map = machine->vmlinux_maps[type]; 2592 2581 int ret = dso__load_kallsyms(map->dso, filename, map, filter); 2593 2582 2594 2583 if (ret > 0) { ··· 2598 2587 * kernel, with modules between them, fixup the end of all 2599 2588 * sections. 2600 2589 */ 2601 - __map_groups__fixup_end(&self->kmaps, type); 2590 + __map_groups__fixup_end(&machine->kmaps, type); 2602 2591 } 2603 2592 2604 2593 return ret; 2605 2594 } 2606 2595 2607 - int machine__load_vmlinux_path(struct machine *self, enum map_type type, 2596 + int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 2608 2597 symbol_filter_t filter) 2609 2598 { 2610 - struct map *map = self->vmlinux_maps[type]; 2599 + struct map *map = machine->vmlinux_maps[type]; 2611 2600 int ret = dso__load_vmlinux_path(map->dso, map, filter); 2612 2601 2613 2602 if (ret > 0) {
+41 -37
tools/perf/util/symbol.h
··· 62 62 char name[0]; 63 63 }; 64 64 65 - void symbol__delete(struct symbol *self); 65 + void symbol__delete(struct symbol *sym); 66 66 67 67 struct strlist; 68 68 ··· 96 96 97 97 extern struct symbol_conf symbol_conf; 98 98 99 - static inline void *symbol__priv(struct symbol *self) 99 + static inline void *symbol__priv(struct symbol *sym) 100 100 { 101 - return ((void *)self) - symbol_conf.priv_size; 101 + return ((void *)sym) - symbol_conf.priv_size; 102 102 } 103 103 104 104 struct ref_reloc_sym { ··· 155 155 156 156 struct dso *dso__new(const char *name); 157 157 struct dso *dso__new_kernel(const char *name); 158 - void dso__delete(struct dso *self); 158 + void dso__delete(struct dso *dso); 159 159 160 - int dso__name_len(const struct dso *self); 160 + int dso__name_len(const struct dso *dso); 161 161 162 - bool dso__loaded(const struct dso *self, enum map_type type); 163 - bool dso__sorted_by_name(const struct dso *self, enum map_type type); 162 + bool dso__loaded(const struct dso *dso, enum map_type type); 163 + bool dso__sorted_by_name(const struct dso *dso, enum map_type type); 164 164 165 - static inline void dso__set_loaded(struct dso *self, enum map_type type) 165 + static inline void dso__set_loaded(struct dso *dso, enum map_type type) 166 166 { 167 - self->loaded |= (1 << type); 167 + dso->loaded |= (1 << type); 168 168 } 169 169 170 - void dso__sort_by_name(struct dso *self, enum map_type type); 170 + void dso__sort_by_name(struct dso *dso, enum map_type type); 171 171 172 172 struct dso *__dsos__findnew(struct list_head *head, const char *name); 173 173 174 - int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 175 - int dso__load_vmlinux(struct dso *self, struct map *map, 174 + int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 175 + int dso__load_vmlinux(struct dso *dso, struct map *map, 176 176 const char *vmlinux, symbol_filter_t filter); 177 - int dso__load_vmlinux_path(struct dso *self, struct map *map, 177 + int dso__load_vmlinux_path(struct dso *dso, struct map *map, 178 178 symbol_filter_t filter); 179 - int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, 179 + int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 180 180 symbol_filter_t filter); 181 - int machine__load_kallsyms(struct machine *self, const char *filename, 181 + int machine__load_kallsyms(struct machine *machine, const char *filename, 182 182 enum map_type type, symbol_filter_t filter); 183 - int machine__load_vmlinux_path(struct machine *self, enum map_type type, 183 + int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 184 184 symbol_filter_t filter); 185 185 186 186 size_t __dsos__fprintf(struct list_head *head, FILE *fp); 187 187 188 - size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits); 189 - size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); 190 - size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); 191 - 192 - size_t dso__fprintf_buildid(struct dso *self, FILE *fp); 193 - size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp); 194 - size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); 188 + size_t machine__fprintf_dsos_buildid(struct machine *machine, 189 + FILE *fp, bool with_hits); 190 + size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); 191 + size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 192 + FILE *fp, bool with_hits); 193 + size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); 194 + size_t dso__fprintf_symbols_by_name(struct dso *dso, 195 + enum map_type type, FILE *fp); 196 + size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); 195 197 196 198 enum symtab_type { 197 199 SYMTAB__KALLSYMS = 0, ··· 209 207 SYMTAB__NOT_FOUND, 210 208 }; 211 209 212 - char dso__symtab_origin(const struct dso *self); 213 - void dso__set_long_name(struct dso *self, char *name); 214 - void dso__set_build_id(struct dso *self, void *build_id); 215 - void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine); 216 - struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); 217 - struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, 210 + char dso__symtab_origin(const struct dso *dso); 211 + void dso__set_long_name(struct dso *dso, char *name); 212 + void dso__set_build_id(struct dso *dso, void *build_id); 213 + void dso__read_running_kernel_build_id(struct dso *dso, 214 + struct machine *machine); 215 + struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 216 + u64 addr); 217 + struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 218 218 const char *name); 219 219 220 220 int filename__read_build_id(const char *filename, void *bf, size_t size); 221 221 int sysfs__read_build_id(const char *filename, void *bf, size_t size); 222 222 bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 223 - int build_id__sprintf(const u8 *self, int len, char *bf); 223 + int build_id__sprintf(const u8 *build_id, int len, char *bf); 224 224 int kallsyms__parse(const char *filename, void *arg, 225 225 int (*process_symbol)(void *arg, const char *name, 226 226 char type, u64 start, u64 end)); 227 227 228 - void machine__destroy_kernel_maps(struct machine *self); 229 - int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); 230 - int machine__create_kernel_maps(struct machine *self); 228 + void machine__destroy_kernel_maps(struct machine *machine); 229 + int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); 230 + int machine__create_kernel_maps(struct machine *machine); 231 231 232 - int machines__create_kernel_maps(struct rb_root *self, pid_t pid); 233 - int machines__create_guest_kernel_maps(struct rb_root *self); 234 - void machines__destroy_guest_kernel_maps(struct rb_root *self); 232 + int machines__create_kernel_maps(struct rb_root *machines, pid_t pid); 233 + int machines__create_guest_kernel_maps(struct rb_root *machines); 234 + void machines__destroy_guest_kernel_maps(struct rb_root *machines); 235 235 236 236 int symbol__init(void); 237 237 void symbol__exit(void); 238 238 bool symbol_type__is_a(char symbol_type, enum map_type map_type); 239 239 240 - size_t machine__fprintf_vmlinux_path(struct machine *self, FILE *fp); 240 + size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 241 241 242 242 #endif /* __PERF_SYMBOL */