diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-25 20:05:40 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-25 20:05:40 -0400 |
| commit | bdc6b758e443c21c39a14c075e5b7e01f095b37b (patch) | |
| tree | 40b98b5abd501cc232f41af03eb078282d7a6327 /kernel | |
| parent | c4a346002bc06046bc51910a7ade3a0c650c3d34 (diff) | |
| parent | 0c9f790fcbdaf8cfb6dd7fb4e88fadf55082e37e (diff) | |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
"Mostly tooling and PMU driver fixes, but also a number of late updates
such as the reworking of the call-chain size limiting logic to make
call-graph recording more robust, plus tooling side changes for the
new 'backwards ring-buffer' extension to the perf ring-buffer"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (34 commits)
perf record: Read from backward ring buffer
perf record: Rename variable to make code clear
perf record: Prevent reading invalid data in record__mmap_read
perf evlist: Add API to pause/resume
perf trace: Use the ptr->name beautifier as default for "filename" args
perf trace: Use the fd->name beautifier as default for "fd" args
perf report: Add srcline_from/to branch sort keys
perf evsel: Record fd into perf_mmap
perf evsel: Add overwrite attribute and check write_backward
perf tools: Set buildid dir under symfs when --symfs is provided
perf trace: Only auto set call-graph to "dwarf" when syscalls are being traced
perf annotate: Sort list of recognised instructions
perf annotate: Fix identification of ARM blt and bls instructions
perf tools: Fix usage of max_stack sysctl
perf callchain: Stop validating callchains by the max_stack sysctl
perf trace: Fix exit_group() formatting
perf top: Use machine->kptr_restrict_warned
perf trace: Warn when trying to resolve kernel addresses with kptr_restrict=1
perf machine: Do not bail out if not managing to read ref reloc symbol
perf/x86/intel/p4: Trival indentation fix, remove space
...
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bpf/stackmap.c | 3 | ||||
| -rw-r--r-- | kernel/events/callchain.c | 36 | ||||
| -rw-r--r-- | kernel/sysctl.c | 11 |
3 files changed, 36 insertions, 14 deletions
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index c8ee35287bfe..080a2dfb5800 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c | |||
| @@ -136,7 +136,8 @@ u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) | |||
| 136 | BPF_F_FAST_STACK_CMP | BPF_F_REUSE_STACKID))) | 136 | BPF_F_FAST_STACK_CMP | BPF_F_REUSE_STACKID))) |
| 137 | return -EINVAL; | 137 | return -EINVAL; |
| 138 | 138 | ||
| 139 | trace = get_perf_callchain(regs, init_nr, kernel, user, false, false); | 139 | trace = get_perf_callchain(regs, init_nr, kernel, user, |
| 140 | sysctl_perf_event_max_stack, false, false); | ||
| 140 | 141 | ||
| 141 | if (unlikely(!trace)) | 142 | if (unlikely(!trace)) |
| 142 | /* couldn't fetch the stack trace */ | 143 | /* couldn't fetch the stack trace */ |
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index b9325e7dcba1..179ef4640964 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c | |||
| @@ -19,11 +19,13 @@ struct callchain_cpus_entries { | |||
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | int sysctl_perf_event_max_stack __read_mostly = PERF_MAX_STACK_DEPTH; | 21 | int sysctl_perf_event_max_stack __read_mostly = PERF_MAX_STACK_DEPTH; |
| 22 | int sysctl_perf_event_max_contexts_per_stack __read_mostly = PERF_MAX_CONTEXTS_PER_STACK; | ||
| 22 | 23 | ||
| 23 | static inline size_t perf_callchain_entry__sizeof(void) | 24 | static inline size_t perf_callchain_entry__sizeof(void) |
| 24 | { | 25 | { |
| 25 | return (sizeof(struct perf_callchain_entry) + | 26 | return (sizeof(struct perf_callchain_entry) + |
| 26 | sizeof(__u64) * sysctl_perf_event_max_stack); | 27 | sizeof(__u64) * (sysctl_perf_event_max_stack + |
| 28 | sysctl_perf_event_max_contexts_per_stack)); | ||
| 27 | } | 29 | } |
| 28 | 30 | ||
| 29 | static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]); | 31 | static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]); |
| @@ -32,12 +34,12 @@ static DEFINE_MUTEX(callchain_mutex); | |||
| 32 | static struct callchain_cpus_entries *callchain_cpus_entries; | 34 | static struct callchain_cpus_entries *callchain_cpus_entries; |
| 33 | 35 | ||
| 34 | 36 | ||
| 35 | __weak void perf_callchain_kernel(struct perf_callchain_entry *entry, | 37 | __weak void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, |
| 36 | struct pt_regs *regs) | 38 | struct pt_regs *regs) |
| 37 | { | 39 | { |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | __weak void perf_callchain_user(struct perf_callchain_entry *entry, | 42 | __weak void perf_callchain_user(struct perf_callchain_entry_ctx *entry, |
| 41 | struct pt_regs *regs) | 43 | struct pt_regs *regs) |
| 42 | { | 44 | { |
| 43 | } | 45 | } |
| @@ -176,14 +178,15 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs) | |||
| 176 | if (!kernel && !user) | 178 | if (!kernel && !user) |
| 177 | return NULL; | 179 | return NULL; |
| 178 | 180 | ||
| 179 | return get_perf_callchain(regs, 0, kernel, user, crosstask, true); | 181 | return get_perf_callchain(regs, 0, kernel, user, sysctl_perf_event_max_stack, crosstask, true); |
| 180 | } | 182 | } |
| 181 | 183 | ||
| 182 | struct perf_callchain_entry * | 184 | struct perf_callchain_entry * |
| 183 | get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, | 185 | get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, |
| 184 | bool crosstask, bool add_mark) | 186 | u32 max_stack, bool crosstask, bool add_mark) |
| 185 | { | 187 | { |
| 186 | struct perf_callchain_entry *entry; | 188 | struct perf_callchain_entry *entry; |
| 189 | struct perf_callchain_entry_ctx ctx; | ||
| 187 | int rctx; | 190 | int rctx; |
| 188 | 191 | ||
| 189 | entry = get_callchain_entry(&rctx); | 192 | entry = get_callchain_entry(&rctx); |
| @@ -193,12 +196,16 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, | |||
| 193 | if (!entry) | 196 | if (!entry) |
| 194 | goto exit_put; | 197 | goto exit_put; |
| 195 | 198 | ||
| 196 | entry->nr = init_nr; | 199 | ctx.entry = entry; |
| 200 | ctx.max_stack = max_stack; | ||
| 201 | ctx.nr = entry->nr = init_nr; | ||
| 202 | ctx.contexts = 0; | ||
| 203 | ctx.contexts_maxed = false; | ||
| 197 | 204 | ||
| 198 | if (kernel && !user_mode(regs)) { | 205 | if (kernel && !user_mode(regs)) { |
| 199 | if (add_mark) | 206 | if (add_mark) |
| 200 | perf_callchain_store(entry, PERF_CONTEXT_KERNEL); | 207 | perf_callchain_store_context(&ctx, PERF_CONTEXT_KERNEL); |
| 201 | perf_callchain_kernel(entry, regs); | 208 | perf_callchain_kernel(&ctx, regs); |
| 202 | } | 209 | } |
| 203 | 210 | ||
| 204 | if (user) { | 211 | if (user) { |
| @@ -214,8 +221,8 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, | |||
| 214 | goto exit_put; | 221 | goto exit_put; |
| 215 | 222 | ||
| 216 | if (add_mark) | 223 | if (add_mark) |
| 217 | perf_callchain_store(entry, PERF_CONTEXT_USER); | 224 | perf_callchain_store_context(&ctx, PERF_CONTEXT_USER); |
| 218 | perf_callchain_user(entry, regs); | 225 | perf_callchain_user(&ctx, regs); |
| 219 | } | 226 | } |
| 220 | } | 227 | } |
| 221 | 228 | ||
| @@ -225,10 +232,15 @@ exit_put: | |||
| 225 | return entry; | 232 | return entry; |
| 226 | } | 233 | } |
| 227 | 234 | ||
| 235 | /* | ||
| 236 | * Used for sysctl_perf_event_max_stack and | ||
| 237 | * sysctl_perf_event_max_contexts_per_stack. | ||
| 238 | */ | ||
| 228 | int perf_event_max_stack_handler(struct ctl_table *table, int write, | 239 | int perf_event_max_stack_handler(struct ctl_table *table, int write, |
| 229 | void __user *buffer, size_t *lenp, loff_t *ppos) | 240 | void __user *buffer, size_t *lenp, loff_t *ppos) |
| 230 | { | 241 | { |
| 231 | int new_value = sysctl_perf_event_max_stack, ret; | 242 | int *value = table->data; |
| 243 | int new_value = *value, ret; | ||
| 232 | struct ctl_table new_table = *table; | 244 | struct ctl_table new_table = *table; |
| 233 | 245 | ||
| 234 | new_table.data = &new_value; | 246 | new_table.data = &new_value; |
| @@ -240,7 +252,7 @@ int perf_event_max_stack_handler(struct ctl_table *table, int write, | |||
| 240 | if (atomic_read(&nr_callchain_events)) | 252 | if (atomic_read(&nr_callchain_events)) |
| 241 | ret = -EBUSY; | 253 | ret = -EBUSY; |
| 242 | else | 254 | else |
| 243 | sysctl_perf_event_max_stack = new_value; | 255 | *value = new_value; |
| 244 | 256 | ||
| 245 | mutex_unlock(&callchain_mutex); | 257 | mutex_unlock(&callchain_mutex); |
| 246 | 258 | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 2effd84d83e3..87b2fc38398b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -1149,13 +1149,22 @@ static struct ctl_table kern_table[] = { | |||
| 1149 | }, | 1149 | }, |
| 1150 | { | 1150 | { |
| 1151 | .procname = "perf_event_max_stack", | 1151 | .procname = "perf_event_max_stack", |
| 1152 | .data = NULL, /* filled in by handler */ | 1152 | .data = &sysctl_perf_event_max_stack, |
| 1153 | .maxlen = sizeof(sysctl_perf_event_max_stack), | 1153 | .maxlen = sizeof(sysctl_perf_event_max_stack), |
| 1154 | .mode = 0644, | 1154 | .mode = 0644, |
| 1155 | .proc_handler = perf_event_max_stack_handler, | 1155 | .proc_handler = perf_event_max_stack_handler, |
| 1156 | .extra1 = &zero, | 1156 | .extra1 = &zero, |
| 1157 | .extra2 = &six_hundred_forty_kb, | 1157 | .extra2 = &six_hundred_forty_kb, |
| 1158 | }, | 1158 | }, |
| 1159 | { | ||
| 1160 | .procname = "perf_event_max_contexts_per_stack", | ||
| 1161 | .data = &sysctl_perf_event_max_contexts_per_stack, | ||
| 1162 | .maxlen = sizeof(sysctl_perf_event_max_contexts_per_stack), | ||
| 1163 | .mode = 0644, | ||
| 1164 | .proc_handler = perf_event_max_stack_handler, | ||
| 1165 | .extra1 = &zero, | ||
| 1166 | .extra2 = &one_thousand, | ||
| 1167 | }, | ||
| 1159 | #endif | 1168 | #endif |
| 1160 | #ifdef CONFIG_KMEMCHECK | 1169 | #ifdef CONFIG_KMEMCHECK |
| 1161 | { | 1170 | { |
