Commit 6155bc14315763cf0f1989b3636ccc2f3e57f0d6
Exists in
ti-lsk-linux-4.1.y
and in
10 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: "Mostly tooling fixes, but also an event groups fix, two PMU driver fixes and a CPU model variant addition" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf: Tighten (and fix) the grouping condition perf/x86/intel: Add model number for Airmont perf/rapl: Fix crash in rapl_scale() perf/x86/intel/uncore: Move uncore_box_init() out of driver initialization perf probe: Fix probing kretprobes perf symbols: Introduce 'for' method to iterate over the symbols with a given name perf probe: Do not rely on map__load() filter to find symbols perf symbols: Introduce method to iterate symbols ordered by name perf symbols: Return the first entry with a given name in find_by_name method perf annotate: Fix memory leaks in LOCK handling perf annotate: Handle ins parsing failures perf scripting perl: Force to use stdbool perf evlist: Remove extraneous 'was' on error message
Showing 13 changed files Side-by-side Diff
- arch/x86/kernel/cpu/perf_event_intel.c
- arch/x86/kernel/cpu/perf_event_intel_rapl.c
- arch/x86/kernel/cpu/perf_event_intel_uncore.c
- arch/x86/kernel/cpu/perf_event_intel_uncore.h
- include/linux/perf_event.h
- kernel/events/core.c
- tools/perf/scripts/perl/Perf-Trace-Util/Context.c
- tools/perf/util/annotate.c
- tools/perf/util/evlist.c
- tools/perf/util/map.h
- tools/perf/util/probe-event.c
- tools/perf/util/symbol.c
- tools/perf/util/symbol.h
arch/x86/kernel/cpu/perf_event_intel.c
... | ... | @@ -2431,6 +2431,7 @@ |
2431 | 2431 | break; |
2432 | 2432 | |
2433 | 2433 | case 55: /* 22nm Atom "Silvermont" */ |
2434 | + case 76: /* 14nm Atom "Airmont" */ | |
2434 | 2435 | case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */ |
2435 | 2436 | memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, |
2436 | 2437 | sizeof(hw_cache_event_ids)); |
arch/x86/kernel/cpu/perf_event_intel_rapl.c
... | ... | @@ -142,7 +142,7 @@ |
142 | 142 | * or use ldexp(count, -32). |
143 | 143 | * Watts = Joules/Time delta |
144 | 144 | */ |
145 | - return v << (32 - __this_cpu_read(rapl_pmu->hw_unit)); | |
145 | + return v << (32 - __this_cpu_read(rapl_pmu)->hw_unit); | |
146 | 146 | } |
147 | 147 | |
148 | 148 | static u64 rapl_event_update(struct perf_event *event) |
arch/x86/kernel/cpu/perf_event_intel_uncore.c
... | ... | @@ -840,7 +840,6 @@ |
840 | 840 | box->phys_id = phys_id; |
841 | 841 | box->pci_dev = pdev; |
842 | 842 | box->pmu = pmu; |
843 | - uncore_box_init(box); | |
844 | 843 | pci_set_drvdata(pdev, box); |
845 | 844 | |
846 | 845 | raw_spin_lock(&uncore_box_lock); |
847 | 846 | |
... | ... | @@ -1004,10 +1003,8 @@ |
1004 | 1003 | pmu = &type->pmus[j]; |
1005 | 1004 | box = *per_cpu_ptr(pmu->box, cpu); |
1006 | 1005 | /* called by uncore_cpu_init? */ |
1007 | - if (box && box->phys_id >= 0) { | |
1008 | - uncore_box_init(box); | |
1006 | + if (box && box->phys_id >= 0) | |
1009 | 1007 | continue; |
1010 | - } | |
1011 | 1008 | |
1012 | 1009 | for_each_online_cpu(k) { |
1013 | 1010 | exist = *per_cpu_ptr(pmu->box, k); |
1014 | 1011 | |
... | ... | @@ -1023,10 +1020,8 @@ |
1023 | 1020 | } |
1024 | 1021 | } |
1025 | 1022 | |
1026 | - if (box) { | |
1023 | + if (box) | |
1027 | 1024 | box->phys_id = phys_id; |
1028 | - uncore_box_init(box); | |
1029 | - } | |
1030 | 1025 | } |
1031 | 1026 | } |
1032 | 1027 | return 0; |
arch/x86/kernel/cpu/perf_event_intel_uncore.h
... | ... | @@ -257,6 +257,14 @@ |
257 | 257 | return box->pmu->type->num_counters; |
258 | 258 | } |
259 | 259 | |
260 | +static inline void uncore_box_init(struct intel_uncore_box *box) | |
261 | +{ | |
262 | + if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { | |
263 | + if (box->pmu->type->ops->init_box) | |
264 | + box->pmu->type->ops->init_box(box); | |
265 | + } | |
266 | +} | |
267 | + | |
260 | 268 | static inline void uncore_disable_box(struct intel_uncore_box *box) |
261 | 269 | { |
262 | 270 | if (box->pmu->type->ops->disable_box) |
... | ... | @@ -265,6 +273,8 @@ |
265 | 273 | |
266 | 274 | static inline void uncore_enable_box(struct intel_uncore_box *box) |
267 | 275 | { |
276 | + uncore_box_init(box); | |
277 | + | |
268 | 278 | if (box->pmu->type->ops->enable_box) |
269 | 279 | box->pmu->type->ops->enable_box(box); |
270 | 280 | } |
... | ... | @@ -285,14 +295,6 @@ |
285 | 295 | struct perf_event *event) |
286 | 296 | { |
287 | 297 | return box->pmu->type->ops->read_counter(box, event); |
288 | -} | |
289 | - | |
290 | -static inline void uncore_box_init(struct intel_uncore_box *box) | |
291 | -{ | |
292 | - if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) { | |
293 | - if (box->pmu->type->ops->init_box) | |
294 | - box->pmu->type->ops->init_box(box); | |
295 | - } | |
296 | 298 | } |
297 | 299 | |
298 | 300 | static inline bool uncore_box_is_fake(struct intel_uncore_box *box) |
include/linux/perf_event.h
... | ... | @@ -450,11 +450,6 @@ |
450 | 450 | #endif /* CONFIG_PERF_EVENTS */ |
451 | 451 | }; |
452 | 452 | |
453 | -enum perf_event_context_type { | |
454 | - task_context, | |
455 | - cpu_context, | |
456 | -}; | |
457 | - | |
458 | 453 | /** |
459 | 454 | * struct perf_event_context - event context structure |
460 | 455 | * |
... | ... | @@ -462,7 +457,6 @@ |
462 | 457 | */ |
463 | 458 | struct perf_event_context { |
464 | 459 | struct pmu *pmu; |
465 | - enum perf_event_context_type type; | |
466 | 460 | /* |
467 | 461 | * Protect the states of the events in the list, |
468 | 462 | * nr_active, and the list: |
kernel/events/core.c
... | ... | @@ -6776,7 +6776,6 @@ |
6776 | 6776 | __perf_event_init_context(&cpuctx->ctx); |
6777 | 6777 | lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); |
6778 | 6778 | lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); |
6779 | - cpuctx->ctx.type = cpu_context; | |
6780 | 6779 | cpuctx->ctx.pmu = pmu; |
6781 | 6780 | |
6782 | 6781 | __perf_cpu_hrtimer_init(cpuctx, cpu); |
... | ... | @@ -7420,7 +7419,19 @@ |
7420 | 7419 | * task or CPU context: |
7421 | 7420 | */ |
7422 | 7421 | if (move_group) { |
7423 | - if (group_leader->ctx->type != ctx->type) | |
7422 | + /* | |
7423 | + * Make sure we're both on the same task, or both | |
7424 | + * per-cpu events. | |
7425 | + */ | |
7426 | + if (group_leader->ctx->task != ctx->task) | |
7427 | + goto err_context; | |
7428 | + | |
7429 | + /* | |
7430 | + * Make sure we're both events for the same CPU; | |
7431 | + * grouping events for different CPUs is broken; since | |
7432 | + * you can never concurrently schedule them anyhow. | |
7433 | + */ | |
7434 | + if (group_leader->cpu != event->cpu) | |
7424 | 7435 | goto err_context; |
7425 | 7436 | } else { |
7426 | 7437 | if (group_leader->ctx != ctx) |
tools/perf/scripts/perl/Perf-Trace-Util/Context.c
tools/perf/util/annotate.c
... | ... | @@ -177,14 +177,17 @@ |
177 | 177 | goto out_free_ops; |
178 | 178 | |
179 | 179 | ops->locked.ins = ins__find(name); |
180 | + free(name); | |
181 | + | |
180 | 182 | if (ops->locked.ins == NULL) |
181 | 183 | goto out_free_ops; |
182 | 184 | |
183 | 185 | if (!ops->locked.ins->ops) |
184 | 186 | return 0; |
185 | 187 | |
186 | - if (ops->locked.ins->ops->parse) | |
187 | - ops->locked.ins->ops->parse(ops->locked.ops); | |
188 | + if (ops->locked.ins->ops->parse && | |
189 | + ops->locked.ins->ops->parse(ops->locked.ops) < 0) | |
190 | + goto out_free_ops; | |
188 | 191 | |
189 | 192 | return 0; |
190 | 193 | |
... | ... | @@ -208,6 +211,13 @@ |
208 | 211 | |
209 | 212 | static void lock__delete(struct ins_operands *ops) |
210 | 213 | { |
214 | + struct ins *ins = ops->locked.ins; | |
215 | + | |
216 | + if (ins && ins->ops->free) | |
217 | + ins->ops->free(ops->locked.ops); | |
218 | + else | |
219 | + ins__delete(ops->locked.ops); | |
220 | + | |
211 | 221 | zfree(&ops->locked.ops); |
212 | 222 | zfree(&ops->target.raw); |
213 | 223 | zfree(&ops->target.name); |
... | ... | @@ -531,8 +541,8 @@ |
531 | 541 | if (!dl->ins->ops) |
532 | 542 | return; |
533 | 543 | |
534 | - if (dl->ins->ops->parse) | |
535 | - dl->ins->ops->parse(&dl->ops); | |
544 | + if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0) | |
545 | + dl->ins = NULL; | |
536 | 546 | } |
537 | 547 | |
538 | 548 | static int disasm_line__parse(char *line, char **namep, char **rawp) |
tools/perf/util/evlist.c
... | ... | @@ -1445,7 +1445,7 @@ |
1445 | 1445 | case ENOENT: |
1446 | 1446 | scnprintf(buf, size, "%s", |
1447 | 1447 | "Error:\tUnable to find debugfs\n" |
1448 | - "Hint:\tWas your kernel was compiled with debugfs support?\n" | |
1448 | + "Hint:\tWas your kernel compiled with debugfs support?\n" | |
1449 | 1449 | "Hint:\tIs the debugfs filesystem mounted?\n" |
1450 | 1450 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); |
1451 | 1451 | break; |
tools/perf/util/map.h
... | ... | @@ -116,6 +116,22 @@ |
116 | 116 | #define map__for_each_symbol(map, pos, n) \ |
117 | 117 | dso__for_each_symbol(map->dso, pos, n, map->type) |
118 | 118 | |
119 | +/* map__for_each_symbol_with_name - iterate over the symbols in the given map | |
120 | + * that have the given name | |
121 | + * | |
122 | + * @map: the 'struct map *' in which symbols itereated | |
123 | + * @sym_name: the symbol name | |
124 | + * @pos: the 'struct symbol *' to use as a loop cursor | |
125 | + * @filter: to use when loading the DSO | |
126 | + */ | |
127 | +#define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \ | |
128 | + for (pos = map__find_symbol_by_name(map, sym_name, filter); \ | |
129 | + pos && strcmp(pos->name, sym_name) == 0; \ | |
130 | + pos = symbol__next_by_name(pos)) | |
131 | + | |
132 | +#define map__for_each_symbol_by_name(map, sym_name, pos) \ | |
133 | + __map__for_each_symbol_by_name(map, sym_name, (pos), NULL) | |
134 | + | |
119 | 135 | typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); |
120 | 136 | |
121 | 137 | void map__init(struct map *map, enum map_type type, |
tools/perf/util/probe-event.c
... | ... | @@ -446,7 +446,7 @@ |
446 | 446 | } |
447 | 447 | |
448 | 448 | for (i = 0; i < ntevs; i++) { |
449 | - if (tevs[i].point.address) { | |
449 | + if (tevs[i].point.address && !tevs[i].point.retprobe) { | |
450 | 450 | tmp = strdup(reloc_sym->name); |
451 | 451 | if (!tmp) |
452 | 452 | return -ENOMEM; |
453 | 453 | |
454 | 454 | |
... | ... | @@ -2193,18 +2193,17 @@ |
2193 | 2193 | return ret; |
2194 | 2194 | } |
2195 | 2195 | |
2196 | -static char *looking_function_name; | |
2197 | -static int num_matched_functions; | |
2198 | - | |
2199 | -static int probe_function_filter(struct map *map __maybe_unused, | |
2200 | - struct symbol *sym) | |
2196 | +static int find_probe_functions(struct map *map, char *name) | |
2201 | 2197 | { |
2202 | - if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && | |
2203 | - strcmp(looking_function_name, sym->name) == 0) { | |
2204 | - num_matched_functions++; | |
2205 | - return 0; | |
2198 | + int found = 0; | |
2199 | + struct symbol *sym; | |
2200 | + | |
2201 | + map__for_each_symbol_by_name(map, name, sym) { | |
2202 | + if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) | |
2203 | + found++; | |
2206 | 2204 | } |
2207 | - return 1; | |
2205 | + | |
2206 | + return found; | |
2208 | 2207 | } |
2209 | 2208 | |
2210 | 2209 | #define strdup_or_goto(str, label) \ |
2211 | 2210 | |
... | ... | @@ -2222,10 +2221,10 @@ |
2222 | 2221 | struct kmap *kmap = NULL; |
2223 | 2222 | struct ref_reloc_sym *reloc_sym = NULL; |
2224 | 2223 | struct symbol *sym; |
2225 | - struct rb_node *nd; | |
2226 | 2224 | struct probe_trace_event *tev; |
2227 | 2225 | struct perf_probe_point *pp = &pev->point; |
2228 | 2226 | struct probe_trace_point *tp; |
2227 | + int num_matched_functions; | |
2229 | 2228 | int ret, i; |
2230 | 2229 | |
2231 | 2230 | /* Init maps of given executable or kernel */ |
... | ... | @@ -2242,10 +2241,8 @@ |
2242 | 2241 | * Load matched symbols: Since the different local symbols may have |
2243 | 2242 | * same name but different addresses, this lists all the symbols. |
2244 | 2243 | */ |
2245 | - num_matched_functions = 0; | |
2246 | - looking_function_name = pp->function; | |
2247 | - ret = map__load(map, probe_function_filter); | |
2248 | - if (ret || num_matched_functions == 0) { | |
2244 | + num_matched_functions = find_probe_functions(map, pp->function); | |
2245 | + if (num_matched_functions == 0) { | |
2249 | 2246 | pr_err("Failed to find symbol %s in %s\n", pp->function, |
2250 | 2247 | target ? : "kernel"); |
2251 | 2248 | ret = -ENOENT; |
... | ... | @@ -2257,7 +2254,7 @@ |
2257 | 2254 | goto out; |
2258 | 2255 | } |
2259 | 2256 | |
2260 | - if (!pev->uprobes) { | |
2257 | + if (!pev->uprobes && !pp->retprobe) { | |
2261 | 2258 | kmap = map__kmap(map); |
2262 | 2259 | reloc_sym = kmap->ref_reloc_sym; |
2263 | 2260 | if (!reloc_sym) { |
... | ... | @@ -2275,7 +2272,8 @@ |
2275 | 2272 | } |
2276 | 2273 | |
2277 | 2274 | ret = 0; |
2278 | - map__for_each_symbol(map, sym, nd) { | |
2275 | + | |
2276 | + map__for_each_symbol_by_name(map, pp->function, sym) { | |
2279 | 2277 | tev = (*tevs) + ret; |
2280 | 2278 | tp = &tev->point; |
2281 | 2279 | if (ret == num_matched_functions) { |
tools/perf/util/symbol.c
... | ... | @@ -396,6 +396,7 @@ |
396 | 396 | const char *name) |
397 | 397 | { |
398 | 398 | struct rb_node *n; |
399 | + struct symbol_name_rb_node *s; | |
399 | 400 | |
400 | 401 | if (symbols == NULL) |
401 | 402 | return NULL; |
... | ... | @@ -403,7 +404,6 @@ |
403 | 404 | n = symbols->rb_node; |
404 | 405 | |
405 | 406 | while (n) { |
406 | - struct symbol_name_rb_node *s; | |
407 | 407 | int cmp; |
408 | 408 | |
409 | 409 | s = rb_entry(n, struct symbol_name_rb_node, rb_node); |
410 | 410 | |
... | ... | @@ -414,10 +414,24 @@ |
414 | 414 | else if (cmp > 0) |
415 | 415 | n = n->rb_right; |
416 | 416 | else |
417 | - return &s->sym; | |
417 | + break; | |
418 | 418 | } |
419 | 419 | |
420 | - return NULL; | |
420 | + if (n == NULL) | |
421 | + return NULL; | |
422 | + | |
423 | + /* return first symbol that has same name (if any) */ | |
424 | + for (n = rb_prev(n); n; n = rb_prev(n)) { | |
425 | + struct symbol_name_rb_node *tmp; | |
426 | + | |
427 | + tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); | |
428 | + if (strcmp(tmp->sym.name, s->sym.name)) | |
429 | + break; | |
430 | + | |
431 | + s = tmp; | |
432 | + } | |
433 | + | |
434 | + return &s->sym; | |
421 | 435 | } |
422 | 436 | |
423 | 437 | struct symbol *dso__find_symbol(struct dso *dso, |
... | ... | @@ -436,6 +450,17 @@ |
436 | 450 | return symbols__next(sym); |
437 | 451 | } |
438 | 452 | |
453 | +struct symbol *symbol__next_by_name(struct symbol *sym) | |
454 | +{ | |
455 | + struct symbol_name_rb_node *s = container_of(sym, struct symbol_name_rb_node, sym); | |
456 | + struct rb_node *n = rb_next(&s->rb_node); | |
457 | + | |
458 | + return n ? &rb_entry(n, struct symbol_name_rb_node, rb_node)->sym : NULL; | |
459 | +} | |
460 | + | |
461 | + /* | |
462 | + * Teturns first symbol that matched with @name. | |
463 | + */ | |
439 | 464 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
440 | 465 | const char *name) |
441 | 466 | { |
tools/perf/util/symbol.h
... | ... | @@ -231,6 +231,7 @@ |
231 | 231 | u64 addr); |
232 | 232 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
233 | 233 | const char *name); |
234 | +struct symbol *symbol__next_by_name(struct symbol *sym); | |
234 | 235 | |
235 | 236 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); |
236 | 237 | struct symbol *dso__next_symbol(struct symbol *sym); |