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

perf: Dynamic pmu types

Extend the perf_pmu_register() interface to allow for named and
dynamic pmu types.

Because we need to support the existing static types we cannot use
dynamic types for everything, hence provide a type argument.

If we want to enumerate the PMUs they need a name, provide one.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101117222056.259707703@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Peter Zijlstra and committed by
Ingo Molnar
2e80a82a 9f58a205

+54 -15
+1 -1
arch/alpha/kernel/perf_event.c
··· 882 882 /* And set up PMU specification */ 883 883 alpha_pmu = &ev67_pmu; 884 884 885 - perf_pmu_register(&pmu); 885 + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 886 886 887 887 return 0; 888 888 }
+1 -1
arch/arm/kernel/perf_event.c
··· 3034 3034 pr_info("no hardware support available\n"); 3035 3035 } 3036 3036 3037 - perf_pmu_register(&pmu); 3037 + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 3038 3038 3039 3039 return 0; 3040 3040 }
+1 -1
arch/powerpc/kernel/perf_event.c
··· 1379 1379 freeze_events_kernel = MMCR0_FCHV; 1380 1380 #endif /* CONFIG_PPC64 */ 1381 1381 1382 - perf_pmu_register(&power_pmu); 1382 + perf_pmu_register(&power_pmu, "cpu", PERF_TYPE_RAW); 1383 1383 perf_cpu_notifier(power_pmu_notifier); 1384 1384 1385 1385 return 0;
+1 -1
arch/powerpc/kernel/perf_event_fsl_emb.c
··· 681 681 pr_info("%s performance monitor hardware support registered\n", 682 682 pmu->name); 683 683 684 - perf_pmu_register(&fsl_emb_pmu); 684 + perf_pmu_register(&fsl_emb_pmu, "cpu", PERF_TYPE_RAW); 685 685 686 686 return 0; 687 687 }
+1 -1
arch/sh/kernel/perf_event.c
··· 389 389 390 390 WARN_ON(_pmu->num_events > MAX_HWEVENTS); 391 391 392 - perf_pmu_register(&pmu); 392 + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 393 393 perf_cpu_notifier(sh_pmu_notifier); 394 394 return 0; 395 395 }
+1 -1
arch/sparc/kernel/perf_event.c
··· 1318 1318 1319 1319 pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type); 1320 1320 1321 - perf_pmu_register(&pmu); 1321 + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 1322 1322 register_die_notifier(&perf_event_nmi_notifier); 1323 1323 1324 1324 return 0;
+1 -1
arch/x86/kernel/cpu/perf_event.c
··· 1465 1465 pr_info("... fixed-purpose events: %d\n", x86_pmu.num_counters_fixed); 1466 1466 pr_info("... event mask: %016Lx\n", x86_pmu.intel_ctrl); 1467 1467 1468 - perf_pmu_register(&pmu); 1468 + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 1469 1469 perf_cpu_notifier(x86_pmu_notifier); 1470 1470 1471 1471 return 0;
+4 -1
include/linux/perf_event.h
··· 588 588 struct pmu { 589 589 struct list_head entry; 590 590 591 + char *name; 592 + int type; 593 + 591 594 int * __percpu pmu_disable_count; 592 595 struct perf_cpu_context * __percpu pmu_cpu_context; 593 596 int task_ctx_nr; ··· 919 916 920 917 #ifdef CONFIG_PERF_EVENTS 921 918 922 - extern int perf_pmu_register(struct pmu *pmu); 919 + extern int perf_pmu_register(struct pmu *pmu, char *name, int type); 923 920 extern void perf_pmu_unregister(struct pmu *pmu); 924 921 925 922 extern int perf_num_counters(void);
+1 -1
kernel/hw_breakpoint.c
··· 641 641 642 642 constraints_initialized = 1; 643 643 644 - perf_pmu_register(&perf_breakpoint); 644 + perf_pmu_register(&perf_breakpoint, "breakpoint", PERF_TYPE_BREAKPOINT); 645 645 646 646 return register_die_notifier(&hw_breakpoint_exceptions_nb); 647 647
+42 -6
kernel/perf_event.c
··· 13 13 #include <linux/mm.h> 14 14 #include <linux/cpu.h> 15 15 #include <linux/smp.h> 16 + #include <linux/idr.h> 16 17 #include <linux/file.h> 17 18 #include <linux/poll.h> 18 19 #include <linux/slab.h> ··· 4962 4961 4963 4962 static inline void perf_tp_register(void) 4964 4963 { 4965 - perf_pmu_register(&perf_tracepoint); 4964 + perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT); 4966 4965 } 4967 4966 4968 4967 static int perf_event_set_filter(struct perf_event *event, void __user *arg) ··· 5306 5305 out: 5307 5306 mutex_unlock(&pmus_lock); 5308 5307 } 5308 + static struct idr pmu_idr; 5309 5309 5310 - int perf_pmu_register(struct pmu *pmu) 5310 + int perf_pmu_register(struct pmu *pmu, char *name, int type) 5311 5311 { 5312 5312 int cpu, ret; 5313 5313 ··· 5318 5316 if (!pmu->pmu_disable_count) 5319 5317 goto unlock; 5320 5318 5319 + pmu->type = -1; 5320 + if (!name) 5321 + goto skip_type; 5322 + pmu->name = name; 5323 + 5324 + if (type < 0) { 5325 + int err = idr_pre_get(&pmu_idr, GFP_KERNEL); 5326 + if (!err) 5327 + goto free_pdc; 5328 + 5329 + err = idr_get_new_above(&pmu_idr, pmu, PERF_TYPE_MAX, &type); 5330 + if (err) { 5331 + ret = err; 5332 + goto free_pdc; 5333 + } 5334 + } 5335 + pmu->type = type; 5336 + 5337 + skip_type: 5321 5338 pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr); 5322 5339 if (pmu->pmu_cpu_context) 5323 5340 goto got_cpu_context; 5324 5341 5325 5342 pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context); 5326 5343 if (!pmu->pmu_cpu_context) 5327 - goto free_pdc; 5344 + goto free_ird; 5328 5345 5329 5346 for_each_possible_cpu(cpu) { 5330 5347 struct perf_cpu_context *cpuctx; ··· 5387 5366 5388 5367 return ret; 5389 5368 5369 + free_idr: 5370 + if (pmu->type >= PERF_TYPE_MAX) 5371 + idr_remove(&pmu_idr, pmu->type); 5372 + 5390 5373 free_pdc: 5391 5374 free_percpu(pmu->pmu_disable_count); 5392 5375 goto unlock; ··· 5410 5385 synchronize_rcu(); 5411 5386 5412 5387 free_percpu(pmu->pmu_disable_count); 5388 + if (pmu->type >= PERF_TYPE_MAX) 5389 + idr_remove(&pmu_idr, pmu->type); 5413 5390 free_pmu_context(pmu); 5414 5391 } 5415 5392 ··· 5421 5394 int idx; 5422 5395 5423 5396 idx = srcu_read_lock(&pmus_srcu); 5397 + 5398 + rcu_read_lock(); 5399 + pmu = idr_find(&pmu_idr, event->attr.type); 5400 + rcu_read_unlock(); 5401 + if (pmu) 5402 + goto unlock; 5403 + 5424 5404 list_for_each_entry_rcu(pmu, &pmus, entry) { 5425 5405 int ret = pmu->event_init(event); 5426 5406 if (!ret) ··· 6589 6555 { 6590 6556 int ret; 6591 6557 6558 + idr_init(&pmu_idr); 6559 + 6592 6560 perf_event_init_all_cpus(); 6593 6561 init_srcu_struct(&pmus_srcu); 6594 - perf_pmu_register(&perf_swevent); 6595 - perf_pmu_register(&perf_cpu_clock); 6596 - perf_pmu_register(&perf_task_clock); 6562 + perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE); 6563 + perf_pmu_register(&perf_cpu_clock, NULL, -1); 6564 + perf_pmu_register(&perf_task_clock, NULL, -1); 6597 6565 perf_tp_register(); 6598 6566 perf_cpu_notifier(perf_cpu_notify); 6599 6567 register_reboot_notifier(&perf_reboot_notifier);