Commit f8ef15d6b9d8e38729cd740a43919adf88468119
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar. * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86: Add Intel IvyBridge event scheduling constraints ftrace: Call ftrace cleanup module notifier after all other notifiers tracing/syscalls: Allow archs to ignore tracing compat syscalls
Showing 5 changed files Side-by-side Diff
arch/x86/include/asm/ftrace.h
... | ... | @@ -72,5 +72,29 @@ |
72 | 72 | #endif /* __ASSEMBLY__ */ |
73 | 73 | #endif /* CONFIG_FUNCTION_TRACER */ |
74 | 74 | |
75 | + | |
76 | +#if !defined(__ASSEMBLY__) && !defined(COMPILE_OFFSETS) | |
77 | + | |
78 | +#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_IA32_EMULATION) | |
79 | +#include <asm/compat.h> | |
80 | + | |
81 | +/* | |
82 | + * Because ia32 syscalls do not map to x86_64 syscall numbers | |
83 | + * this screws up the trace output when tracing a ia32 task. | |
84 | + * Instead of reporting bogus syscalls, just do not trace them. | |
85 | + * | |
86 | + * If the user realy wants these, then they should use the | |
87 | + * raw syscall tracepoints with filtering. | |
88 | + */ | |
89 | +#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1 | |
90 | +static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) | |
91 | +{ | |
92 | + if (is_compat_task()) | |
93 | + return true; | |
94 | + return false; | |
95 | +} | |
96 | +#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_IA32_EMULATION */ | |
97 | +#endif /* !__ASSEMBLY__ && !COMPILE_OFFSETS */ | |
98 | + | |
75 | 99 | #endif /* _ASM_X86_FTRACE_H */ |
arch/x86/include/asm/thread_info.h
arch/x86/kernel/cpu/perf_event_intel.c
... | ... | @@ -107,6 +107,27 @@ |
107 | 107 | EVENT_CONSTRAINT_END |
108 | 108 | }; |
109 | 109 | |
110 | +static struct event_constraint intel_ivb_event_constraints[] __read_mostly = | |
111 | +{ | |
112 | + FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | |
113 | + FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | |
114 | + FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ | |
115 | + INTEL_UEVENT_CONSTRAINT(0x0148, 0x4), /* L1D_PEND_MISS.PENDING */ | |
116 | + INTEL_UEVENT_CONSTRAINT(0x0279, 0xf), /* IDQ.EMTPY */ | |
117 | + INTEL_UEVENT_CONSTRAINT(0x019c, 0xf), /* IDQ_UOPS_NOT_DELIVERED.CORE */ | |
118 | + INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */ | |
119 | + INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */ | |
120 | + INTEL_UEVENT_CONSTRAINT(0x06a3, 0xf), /* CYCLE_ACTIVITY.STALLS_LDM_PENDING */ | |
121 | + INTEL_UEVENT_CONSTRAINT(0x08a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */ | |
122 | + INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */ | |
123 | + INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */ | |
124 | + INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */ | |
125 | + INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ | |
126 | + INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ | |
127 | + INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ | |
128 | + EVENT_CONSTRAINT_END | |
129 | +}; | |
130 | + | |
110 | 131 | static struct extra_reg intel_westmere_extra_regs[] __read_mostly = |
111 | 132 | { |
112 | 133 | INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0), |
... | ... | @@ -2095,7 +2116,7 @@ |
2095 | 2116 | |
2096 | 2117 | intel_pmu_lbr_init_snb(); |
2097 | 2118 | |
2098 | - x86_pmu.event_constraints = intel_snb_event_constraints; | |
2119 | + x86_pmu.event_constraints = intel_ivb_event_constraints; | |
2099 | 2120 | x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints; |
2100 | 2121 | x86_pmu.pebs_aliases = intel_pebs_aliases_snb; |
2101 | 2122 | x86_pmu.extra_regs = intel_snb_extra_regs; |
kernel/trace/ftrace.c
... | ... | @@ -3996,37 +3996,51 @@ |
3996 | 3996 | ftrace_process_locs(mod, start, end); |
3997 | 3997 | } |
3998 | 3998 | |
3999 | -static int ftrace_module_notify(struct notifier_block *self, | |
4000 | - unsigned long val, void *data) | |
3999 | +static int ftrace_module_notify_enter(struct notifier_block *self, | |
4000 | + unsigned long val, void *data) | |
4001 | 4001 | { |
4002 | 4002 | struct module *mod = data; |
4003 | 4003 | |
4004 | - switch (val) { | |
4005 | - case MODULE_STATE_COMING: | |
4004 | + if (val == MODULE_STATE_COMING) | |
4006 | 4005 | ftrace_init_module(mod, mod->ftrace_callsites, |
4007 | 4006 | mod->ftrace_callsites + |
4008 | 4007 | mod->num_ftrace_callsites); |
4009 | - break; | |
4010 | - case MODULE_STATE_GOING: | |
4008 | + return 0; | |
4009 | +} | |
4010 | + | |
4011 | +static int ftrace_module_notify_exit(struct notifier_block *self, | |
4012 | + unsigned long val, void *data) | |
4013 | +{ | |
4014 | + struct module *mod = data; | |
4015 | + | |
4016 | + if (val == MODULE_STATE_GOING) | |
4011 | 4017 | ftrace_release_mod(mod); |
4012 | - break; | |
4013 | - } | |
4014 | 4018 | |
4015 | 4019 | return 0; |
4016 | 4020 | } |
4017 | 4021 | #else |
4018 | -static int ftrace_module_notify(struct notifier_block *self, | |
4019 | - unsigned long val, void *data) | |
4022 | +static int ftrace_module_notify_enter(struct notifier_block *self, | |
4023 | + unsigned long val, void *data) | |
4020 | 4024 | { |
4021 | 4025 | return 0; |
4022 | 4026 | } |
4027 | +static int ftrace_module_notify_exit(struct notifier_block *self, | |
4028 | + unsigned long val, void *data) | |
4029 | +{ | |
4030 | + return 0; | |
4031 | +} | |
4023 | 4032 | #endif /* CONFIG_MODULES */ |
4024 | 4033 | |
4025 | -struct notifier_block ftrace_module_nb = { | |
4026 | - .notifier_call = ftrace_module_notify, | |
4034 | +struct notifier_block ftrace_module_enter_nb = { | |
4035 | + .notifier_call = ftrace_module_notify_enter, | |
4027 | 4036 | .priority = INT_MAX, /* Run before anything that can use kprobes */ |
4028 | 4037 | }; |
4029 | 4038 | |
4039 | +struct notifier_block ftrace_module_exit_nb = { | |
4040 | + .notifier_call = ftrace_module_notify_exit, | |
4041 | + .priority = INT_MIN, /* Run after anything that can remove kprobes */ | |
4042 | +}; | |
4043 | + | |
4030 | 4044 | extern unsigned long __start_mcount_loc[]; |
4031 | 4045 | extern unsigned long __stop_mcount_loc[]; |
4032 | 4046 | |
4033 | 4047 | |
... | ... | @@ -4058,9 +4072,13 @@ |
4058 | 4072 | __start_mcount_loc, |
4059 | 4073 | __stop_mcount_loc); |
4060 | 4074 | |
4061 | - ret = register_module_notifier(&ftrace_module_nb); | |
4075 | + ret = register_module_notifier(&ftrace_module_enter_nb); | |
4062 | 4076 | if (ret) |
4063 | - pr_warning("Failed to register trace ftrace module notifier\n"); | |
4077 | + pr_warning("Failed to register trace ftrace module enter notifier\n"); | |
4078 | + | |
4079 | + ret = register_module_notifier(&ftrace_module_exit_nb); | |
4080 | + if (ret) | |
4081 | + pr_warning("Failed to register trace ftrace module exit notifier\n"); | |
4064 | 4082 | |
4065 | 4083 | set_ftrace_early_filters(); |
4066 | 4084 |
kernel/trace/trace_syscalls.c
1 | 1 | #include <trace/syscall.h> |
2 | 2 | #include <trace/events/syscalls.h> |
3 | +#include <linux/syscalls.h> | |
3 | 4 | #include <linux/slab.h> |
4 | 5 | #include <linux/kernel.h> |
5 | 6 | #include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */ |
... | ... | @@ -47,6 +48,38 @@ |
47 | 48 | } |
48 | 49 | #endif |
49 | 50 | |
51 | +#ifdef ARCH_TRACE_IGNORE_COMPAT_SYSCALLS | |
52 | +/* | |
53 | + * Some architectures that allow for 32bit applications | |
54 | + * to run on a 64bit kernel, do not map the syscalls for | |
55 | + * the 32bit tasks the same as they do for 64bit tasks. | |
56 | + * | |
57 | + * *cough*x86*cough* | |
58 | + * | |
59 | + * In such a case, instead of reporting the wrong syscalls, | |
60 | + * simply ignore them. | |
61 | + * | |
62 | + * For an arch to ignore the compat syscalls it needs to | |
63 | + * define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS as well as | |
64 | + * define the function arch_trace_is_compat_syscall() to let | |
65 | + * the tracing system know that it should ignore it. | |
66 | + */ | |
67 | +static int | |
68 | +trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs) | |
69 | +{ | |
70 | + if (unlikely(arch_trace_is_compat_syscall(regs))) | |
71 | + return -1; | |
72 | + | |
73 | + return syscall_get_nr(task, regs); | |
74 | +} | |
75 | +#else | |
76 | +static inline int | |
77 | +trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs) | |
78 | +{ | |
79 | + return syscall_get_nr(task, regs); | |
80 | +} | |
81 | +#endif /* ARCH_TRACE_IGNORE_COMPAT_SYSCALLS */ | |
82 | + | |
50 | 83 | static __init struct syscall_metadata * |
51 | 84 | find_syscall_meta(unsigned long syscall) |
52 | 85 | { |
53 | 86 | |
54 | 87 | |
... | ... | @@ -276,10 +309,10 @@ |
276 | 309 | struct syscall_metadata *sys_data; |
277 | 310 | struct ring_buffer_event *event; |
278 | 311 | struct ring_buffer *buffer; |
279 | - int size; | |
280 | 312 | int syscall_nr; |
313 | + int size; | |
281 | 314 | |
282 | - syscall_nr = syscall_get_nr(current, regs); | |
315 | + syscall_nr = trace_get_syscall_nr(current, regs); | |
283 | 316 | if (syscall_nr < 0) |
284 | 317 | return; |
285 | 318 | if (!test_bit(syscall_nr, enabled_enter_syscalls)) |
... | ... | @@ -313,7 +346,7 @@ |
313 | 346 | struct ring_buffer *buffer; |
314 | 347 | int syscall_nr; |
315 | 348 | |
316 | - syscall_nr = syscall_get_nr(current, regs); | |
349 | + syscall_nr = trace_get_syscall_nr(current, regs); | |
317 | 350 | if (syscall_nr < 0) |
318 | 351 | return; |
319 | 352 | if (!test_bit(syscall_nr, enabled_exit_syscalls)) |
... | ... | @@ -502,7 +535,7 @@ |
502 | 535 | int rctx; |
503 | 536 | int size; |
504 | 537 | |
505 | - syscall_nr = syscall_get_nr(current, regs); | |
538 | + syscall_nr = trace_get_syscall_nr(current, regs); | |
506 | 539 | if (syscall_nr < 0) |
507 | 540 | return; |
508 | 541 | if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) |
... | ... | @@ -578,7 +611,7 @@ |
578 | 611 | int rctx; |
579 | 612 | int size; |
580 | 613 | |
581 | - syscall_nr = syscall_get_nr(current, regs); | |
614 | + syscall_nr = trace_get_syscall_nr(current, regs); | |
582 | 615 | if (syscall_nr < 0) |
583 | 616 | return; |
584 | 617 | if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) |