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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull perf fixes from Ingo Molnar:
"Some tooling fixes plus three kernel fixes: a memory leak fix, a
statistics fix and a crash fix"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf/x86/intel/uncore: Fix memory leaks on allocation failures
perf/core: Fix cgroup time when scheduling descendants
perf/core: Avoid freeing static PMU contexts when PMU is unregistered
tools include uapi bpf.h: Sync kernel ABI header with tooling header
perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU
perf script: Add missing separator for "-F ip,brstack" (and brstackoff)
perf callchain: Compare dsos (as well) for CCKEY_FUNCTION

+81 -33
+10 -2
arch/x86/events/intel/uncore.c
··· 822 822 pmus[i].type = type; 823 823 pmus[i].boxes = kzalloc(size, GFP_KERNEL); 824 824 if (!pmus[i].boxes) 825 - return -ENOMEM; 825 + goto err; 826 826 } 827 827 828 828 type->pmus = pmus; ··· 836 836 attr_group = kzalloc(sizeof(struct attribute *) * (i + 1) + 837 837 sizeof(*attr_group), GFP_KERNEL); 838 838 if (!attr_group) 839 - return -ENOMEM; 839 + goto err; 840 840 841 841 attrs = (struct attribute **)(attr_group + 1); 842 842 attr_group->name = "events"; ··· 849 849 } 850 850 851 851 type->pmu_group = &uncore_pmu_attr_group; 852 + 852 853 return 0; 854 + 855 + err: 856 + for (i = 0; i < type->num_boxes; i++) 857 + kfree(pmus[i].boxes); 858 + kfree(pmus); 859 + 860 + return -ENOMEM; 853 861 } 854 862 855 863 static int __init
+9 -1
kernel/events/core.c
··· 662 662 /* 663 663 * Do not update time when cgroup is not active 664 664 */ 665 - if (cgrp == event->cgrp) 665 + if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup)) 666 666 __update_cgrp_time(event->cgrp); 667 667 } 668 668 ··· 8955 8955 8956 8956 static void free_pmu_context(struct pmu *pmu) 8957 8957 { 8958 + /* 8959 + * Static contexts such as perf_sw_context have a global lifetime 8960 + * and may be shared between different PMUs. Avoid freeing them 8961 + * when a single PMU is going away. 8962 + */ 8963 + if (pmu->task_ctx_nr > perf_invalid_context) 8964 + return; 8965 + 8958 8966 mutex_lock(&pmus_lock); 8959 8967 free_percpu(pmu->pmu_cpu_context); 8960 8968 mutex_unlock(&pmus_lock);
+1 -1
tools/include/uapi/linux/bpf.h
··· 312 312 * jump into another BPF program 313 313 * @ctx: context pointer passed to next program 314 314 * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY 315 - * @index: index inside array that selects specific program to run 315 + * @index: 32-bit index inside array that selects specific program to run 316 316 * Return: 0 on success or negative error 317 317 * 318 318 * int bpf_clone_redirect(skb, ifindex, flags)
+2 -2
tools/perf/builtin-script.c
··· 586 586 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); 587 587 } 588 588 589 - printf("0x%"PRIx64, from); 589 + printf(" 0x%"PRIx64, from); 590 590 if (PRINT_FIELD(DSO)) { 591 591 printf("("); 592 592 map__fprintf_dsoname(alf.map, stdout); ··· 681 681 if (alt.map && !alt.map->dso->adjust_symbols) 682 682 to = map__map_ip(alt.map, to); 683 683 684 - printf("0x%"PRIx64, from); 684 + printf(" 0x%"PRIx64, from); 685 685 if (PRINT_FIELD(DSO)) { 686 686 printf("("); 687 687 map__fprintf_dsoname(alf.map, stdout);
+5 -1
tools/perf/util/callchain.c
··· 685 685 { 686 686 struct symbol *sym = node->sym; 687 687 u64 left, right; 688 + struct dso *left_dso = NULL; 689 + struct dso *right_dso = NULL; 688 690 689 691 if (callchain_param.key == CCKEY_SRCLINE) { 690 692 enum match_result match = match_chain_srcline(node, cnode); ··· 698 696 if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) { 699 697 left = cnode->ms.sym->start; 700 698 right = sym->start; 699 + left_dso = cnode->ms.map->dso; 700 + right_dso = node->map->dso; 701 701 } else { 702 702 left = cnode->ip; 703 703 right = node->ip; 704 704 } 705 705 706 - if (left == right) { 706 + if (left == right && left_dso == right_dso) { 707 707 if (node->branch) { 708 708 cnode->branch_count++; 709 709
+5 -4
tools/perf/util/parse-events.c
··· 309 309 static struct perf_evsel * 310 310 __add_event(struct list_head *list, int *idx, 311 311 struct perf_event_attr *attr, 312 - char *name, struct cpu_map *cpus, 312 + char *name, struct perf_pmu *pmu, 313 313 struct list_head *config_terms, bool auto_merge_stats) 314 314 { 315 315 struct perf_evsel *evsel; 316 + struct cpu_map *cpus = pmu ? pmu->cpus : NULL; 316 317 317 318 event_attr_init(attr); 318 319 ··· 324 323 (*idx)++; 325 324 evsel->cpus = cpu_map__get(cpus); 326 325 evsel->own_cpus = cpu_map__get(cpus); 327 - evsel->system_wide = !!cpus; 326 + evsel->system_wide = pmu ? pmu->is_uncore : false; 328 327 evsel->auto_merge_stats = auto_merge_stats; 329 328 330 329 if (name) ··· 1234 1233 1235 1234 if (!head_config) { 1236 1235 attr.type = pmu->type; 1237 - evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu->cpus, NULL, auto_merge_stats); 1236 + evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); 1238 1237 return evsel ? 0 : -ENOMEM; 1239 1238 } 1240 1239 ··· 1255 1254 return -EINVAL; 1256 1255 1257 1256 evsel = __add_event(list, &parse_state->idx, &attr, 1258 - get_config_name(head_config), pmu->cpus, 1257 + get_config_name(head_config), pmu, 1259 1258 &config_terms, auto_merge_stats); 1260 1259 if (evsel) { 1261 1260 evsel->unit = info.unit;
+48 -22
tools/perf/util/pmu.c
··· 470 470 closedir(dir); 471 471 } 472 472 473 - static struct cpu_map *pmu_cpumask(const char *name) 473 + static struct cpu_map *__pmu_cpumask(const char *path) 474 474 { 475 - struct stat st; 476 - char path[PATH_MAX]; 477 475 FILE *file; 478 476 struct cpu_map *cpus; 479 - const char *sysfs = sysfs__mountpoint(); 480 - const char *templates[] = { 481 - "%s/bus/event_source/devices/%s/cpumask", 482 - "%s/bus/event_source/devices/%s/cpus", 483 - NULL 484 - }; 485 - const char **template; 486 - 487 - if (!sysfs) 488 - return NULL; 489 - 490 - for (template = templates; *template; template++) { 491 - snprintf(path, PATH_MAX, *template, sysfs, name); 492 - if (stat(path, &st) == 0) 493 - break; 494 - } 495 - 496 - if (!*template) 497 - return NULL; 498 477 499 478 file = fopen(path, "r"); 500 479 if (!file) ··· 482 503 cpus = cpu_map__read(file); 483 504 fclose(file); 484 505 return cpus; 506 + } 507 + 508 + /* 509 + * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 510 + * may have a "cpus" file. 511 + */ 512 + #define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask" 513 + #define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus" 514 + 515 + static struct cpu_map *pmu_cpumask(const char *name) 516 + { 517 + char path[PATH_MAX]; 518 + struct cpu_map *cpus; 519 + const char *sysfs = sysfs__mountpoint(); 520 + const char *templates[] = { 521 + CPUS_TEMPLATE_UNCORE, 522 + CPUS_TEMPLATE_CPU, 523 + NULL 524 + }; 525 + const char **template; 526 + 527 + if (!sysfs) 528 + return NULL; 529 + 530 + for (template = templates; *template; template++) { 531 + snprintf(path, PATH_MAX, *template, sysfs, name); 532 + cpus = __pmu_cpumask(path); 533 + if (cpus) 534 + return cpus; 535 + } 536 + 537 + return NULL; 538 + } 539 + 540 + static bool pmu_is_uncore(const char *name) 541 + { 542 + char path[PATH_MAX]; 543 + struct cpu_map *cpus; 544 + const char *sysfs = sysfs__mountpoint(); 545 + 546 + snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name); 547 + cpus = __pmu_cpumask(path); 548 + cpu_map__put(cpus); 549 + 550 + return !!cpus; 485 551 } 486 552 487 553 /* ··· 640 616 return NULL; 641 617 642 618 pmu->cpus = pmu_cpumask(name); 619 + 620 + pmu->is_uncore = pmu_is_uncore(name); 643 621 644 622 INIT_LIST_HEAD(&pmu->format); 645 623 INIT_LIST_HEAD(&pmu->aliases);
+1
tools/perf/util/pmu.h
··· 22 22 char *name; 23 23 __u32 type; 24 24 bool selectable; 25 + bool is_uncore; 25 26 struct perf_event_attr *default_config; 26 27 struct cpu_map *cpus; 27 28 struct list_head format; /* HEAD struct perf_pmu_format -> list */