linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH 0/8] perf sysfs bits
@ 2010-11-17 22:17 Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 1/8] perf, x86: Fixup Kconfig deps Peter Zijlstra
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra


Another version of the perf sysfs bits.

Thanks to Kay for lots of help and feedback..



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 1/8] perf, x86: Fixup Kconfig deps
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-11-26 15:01   ` [tip:perf/core] " tip-bot for Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations Peter Zijlstra
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-i386-fix-kconfig.patch --]
[-- Type: text/plain, Size: 700 bytes --]

This leads to a Kconfig dep inversion, x86 selects PERF_EVENT (due to
a hw_breakpoint dep) but doesn't unconditionally provide
HAVE_PERF_EVENT.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 arch/x86/Kconfig |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6/arch/x86/Kconfig
===================================================================
--- linux-2.6.orig/arch/x86/Kconfig
+++ linux-2.6/arch/x86/Kconfig
@@ -21,7 +21,7 @@ config X86
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
-	select HAVE_PERF_EVENTS if (!M386 && !M486)
+	select HAVE_PERF_EVENTS
 	select HAVE_IRQ_WORK
 	select HAVE_IOREMAP_PROT
 	select HAVE_KPROBES



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 1/8] perf, x86: Fixup Kconfig deps Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-11-25 10:25   ` Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 3/8] perf: Move perf_event_init() into main.c Peter Zijlstra
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-fix-hw-init.patch --]
[-- Type: text/plain, Size: 6490 bytes --]

Currently architectures use various random locations to init the PMU
driver, for some this happens before the perf core code is
initialized.

In order to avoid calling perf_pmu_register() before the core code is
up and running and able to deal with it, move all arch init to at
least early_initcall (some archs use a later init, which is fine).

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 arch/alpha/include/asm/perf_event.h |    6 ------
 arch/alpha/kernel/irq_alpha.c       |    2 --
 arch/alpha/kernel/perf_event.c      |    9 ++++++---
 arch/sparc/include/asm/perf_event.h |    4 ----
 arch/sparc/kernel/nmi.c             |    2 --
 arch/sparc/kernel/perf_event.c      |    7 +++++--
 arch/x86/include/asm/perf_event.h   |    2 --
 arch/x86/kernel/cpu/common.c        |    1 -
 arch/x86/kernel/cpu/perf_event.c    |    9 ++++++---
 9 files changed, 17 insertions(+), 25 deletions(-)

Index: linux-2.6/arch/alpha/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/alpha/include/asm/perf_event.h
+++ linux-2.6/arch/alpha/include/asm/perf_event.h
@@ -1,10 +1,4 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-#ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
-#else
-static inline void init_hw_perf_events(void)    { }
-#endif
-
 #endif /* __ASM_ALPHA_PERF_EVENT_H */
Index: linux-2.6/arch/alpha/kernel/irq_alpha.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_alpha.c
+++ linux-2.6/arch/alpha/kernel/irq_alpha.c
@@ -112,8 +112,6 @@ init_IRQ(void)
 	wrent(entInt, 0);
 
 	alpha_mv.init_irq();
-
-	init_hw_perf_events();
 }
 
 /*
Index: linux-2.6/arch/alpha/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/perf_event.c
+++ linux-2.6/arch/alpha/kernel/perf_event.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
+#include <linux/init.h>
 
 #include <asm/hwrpb.h>
 #include <asm/atomic.h>
@@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler
 /*
  * Init call to initialise performance events at kernel startup.
  */
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_cpu()) {
 		pr_cont("No support for your CPU.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported CPU type!\n");
@@ -882,5 +883,7 @@ void __init init_hw_perf_events(void)
 	alpha_pmu = &ev67_pmu;
 
 	perf_pmu_register(&pmu);
-}
 
+	return 0;
+}
+early_initcall(init_hw_perf_events);
Index: linux-2.6/arch/sparc/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/sparc/include/asm/perf_event.h
+++ linux-2.6/arch/sparc/include/asm/perf_event.h
@@ -4,8 +4,6 @@
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
-extern void init_hw_perf_events(void);
-
 #define perf_arch_fetch_caller_regs(regs, ip)		\
 do {							\
 	unsigned long _pstate, _asi, _pil, _i7, _fp;	\
@@ -26,8 +24,6 @@ do {							\
 	(regs)->u_regs[UREG_I6] = _fp;			\
 	(regs)->u_regs[UREG_I7] = _i7;			\
 } while (0)
-#else
-static inline void init_hw_perf_events(void)	{ }
 #endif
 
 #endif
Index: linux-2.6/arch/sparc/kernel/nmi.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/nmi.c
+++ linux-2.6/arch/sparc/kernel/nmi.c
@@ -270,8 +270,6 @@ int __init nmi_init(void)
 			atomic_set(&nmi_active, -1);
 		}
 	}
-	if (!err)
-		init_hw_perf_events();
 
 	return err;
 }
Index: linux-2.6/arch/sparc/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/perf_event.c
+++ linux-2.6/arch/sparc/kernel/perf_event.c
@@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void)
 	return false;
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
 	perf_pmu_register(&pmu);
 	register_die_notifier(&perf_event_nmi_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_event);
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
Index: linux-2.6/arch/x86/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/perf_event.h
+++ linux-2.6/arch/x86/include/asm/perf_event.h
@@ -125,7 +125,6 @@ union cpuid10_edx {
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
 #ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
 extern void perf_events_lapic_init(void);
 
 #define PERF_EVENT_INDEX_OFFSET			0
@@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(str
 }
 
 #else
-static inline void init_hw_perf_events(void)		{ }
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
Index: linux-2.6/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6/arch/x86/kernel/cpu/common.c
@@ -894,7 +894,6 @@ void __init identify_boot_cpu(void)
 #else
 	vgetcpu_set_mode();
 #endif
-	init_hw_perf_events();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c
+++ linux-2.6/arch/x86/kernel/cpu/perf_event.c
@@ -1348,7 +1348,7 @@ static void __init pmu_check_apic(void)
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1363,11 +1363,11 @@ void __init init_hw_perf_events(void)
 		err = amd_pmu_init();
 		break;
 	default:
-		return;
+		return 0;
 	}
 	if (err != 0) {
 		pr_cont("no PMU driver, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pmu_check_apic();
@@ -1420,7 +1420,10 @@ void __init init_hw_perf_events(void)
 
 	perf_pmu_register(&pmu);
 	perf_cpu_notifier(x86_pmu_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_events);
 
 static inline void x86_pmu_read(struct perf_event *event)
 {



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 3/8] perf: Move perf_event_init() into main.c
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 1/8] perf, x86: Fixup Kconfig deps Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-12-16 12:32   ` [tip:perf/core] " tip-bot for Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 4/8] perf: Use early_initcall() for tracepoint and breakpoint init Peter Zijlstra
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-fix-init.patch --]
[-- Type: text/plain, Size: 1193 bytes --]

Currently we call perf_event_init() from sched_init(). In order to
make it more obvious move it to the cannnonical location.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 init/main.c    |    2 ++
 kernel/sched.c |    2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

Index: linux-2.6/init/main.c
===================================================================
--- linux-2.6.orig/init/main.c
+++ linux-2.6/init/main.c
@@ -68,6 +68,7 @@
 #include <linux/sfi.h>
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
+#include <linux/perf_event.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -604,6 +605,7 @@ asmlinkage void __init start_kernel(void
 				"enabled *very* early, fixing it\n");
 		local_irq_disable();
 	}
+	perf_event_init();
 	rcu_init();
 	radix_tree_init();
 	/* init some links before init_ISA_irqs() */
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -7876,8 +7876,6 @@ void __init sched_init(void)
 		zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
 #endif /* SMP */
 
-	perf_event_init();
-
 	scheduler_running = 1;
 }
 



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 4/8] perf: Use early_initcall() for tracepoint and breakpoint init
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
                   ` (2 preceding siblings ...)
  2010-11-17 22:17 ` [RFC][PATCH 3/8] perf: Move perf_event_init() into main.c Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 5/8] init: Initialized IRD earlier Peter Zijlstra
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-fix-tp-bp-init.patch --]
[-- Type: text/plain, Size: 1580 bytes --]

Just like other pmu implementations, use early_initcall().

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 kernel/hw_breakpoint.c |    2 +-
 kernel/perf_event.c    |    9 +++------
 2 files changed, 4 insertions(+), 7 deletions(-)

Index: linux-2.6/kernel/hw_breakpoint.c
===================================================================
--- linux-2.6.orig/kernel/hw_breakpoint.c
+++ linux-2.6/kernel/hw_breakpoint.c
@@ -655,6 +655,6 @@ static int __init init_hw_breakpoint(voi
 
 	return -ENOMEM;
 }
-core_initcall(init_hw_breakpoint);
+early_initcall(init_hw_breakpoint);
 
 
Index: linux-2.6/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/kernel/perf_event.c
+++ linux-2.6/kernel/perf_event.c
@@ -4831,10 +4831,12 @@ static struct pmu perf_tracepoint = {
 	.read		= perf_swevent_read,
 };
 
-static inline void perf_tp_register(void)
+static __init int perf_tp_init(void)
 {
 	perf_pmu_register(&perf_tracepoint);
+	return 0;
 }
+early_initcall(perf_tp_init);
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
 {
@@ -4861,10 +4863,6 @@ static void perf_event_free_filter(struc
 
 #else
 
-static inline void perf_tp_register(void)
-{
-}
-
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
 {
 	return -ENOENT;
@@ -6365,6 +6363,5 @@ void __init perf_event_init(void)
 	perf_pmu_register(&perf_swevent);
 	perf_pmu_register(&perf_cpu_clock);
 	perf_pmu_register(&perf_task_clock);
-	perf_tp_register();
 	perf_cpu_notifier(perf_cpu_notify);
 }



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 5/8] init: Initialized IRD earlier
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
                   ` (3 preceding siblings ...)
  2010-11-17 22:17 ` [RFC][PATCH 4/8] perf: Use early_initcall() for tracepoint and breakpoint init Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-12-16 12:32   ` [tip:perf/core] init: Initialized IDR earlier tip-bot for Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 6/8] perf: Dynamic pmu types Peter Zijlstra
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: init-earlier-idx.patch --]
[-- Type: text/plain, Size: 818 bytes --]

perf_event_init() wants to start using IDR trees, its needs in turn
are satisfied by mm_init().

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 init/main.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6/init/main.c
===================================================================
--- linux-2.6.orig/init/main.c
+++ linux-2.6/init/main.c
@@ -605,6 +605,7 @@ asmlinkage void __init start_kernel(void
 				"enabled *very* early, fixing it\n");
 		local_irq_disable();
 	}
+	idr_init_cache();
 	perf_event_init();
 	rcu_init();
 	radix_tree_init();
@@ -661,7 +662,6 @@ asmlinkage void __init start_kernel(void
 	enable_debug_pagealloc();
 	kmemleak_init();
 	debug_objects_mem_init();
-	idr_init_cache();
 	setup_per_cpu_pageset();
 	numa_policy_init();
 	if (late_time_init)



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 6/8] perf: Dynamic pmu types
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
                   ` (4 preceding siblings ...)
  2010-11-17 22:17 ` [RFC][PATCH 5/8] init: Initialized IRD earlier Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-12-16 12:32   ` [tip:perf/core] " tip-bot for Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 7/8] perf: Sysfs enumeration Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 8/8] perf: Sysfs events Peter Zijlstra
  7 siblings, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-dynamic-id-register.patch --]
[-- Type: text/plain, Size: 8495 bytes --]

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>
---
 arch/alpha/kernel/perf_event.c           |    2 -
 arch/arm/kernel/perf_event.c             |    2 -
 arch/powerpc/kernel/perf_event.c         |    2 -
 arch/powerpc/kernel/perf_event_fsl_emb.c |    2 -
 arch/sh/kernel/perf_event.c              |    2 -
 arch/sparc/kernel/perf_event.c           |    2 -
 arch/x86/kernel/cpu/perf_event.c         |    2 -
 include/linux/perf_event.h               |    5 ++-
 kernel/hw_breakpoint.c                   |    2 -
 kernel/perf_event.c                      |   49 +++++++++++++++++++++++++++----
 10 files changed, 55 insertions(+), 15 deletions(-)

Index: linux-2.6/include/linux/perf_event.h
===================================================================
--- linux-2.6.orig/include/linux/perf_event.h
+++ linux-2.6/include/linux/perf_event.h
@@ -578,6 +578,9 @@ struct perf_event;
 struct pmu {
 	struct list_head		entry;
 
+	char				*name;
+	int				type;
+
 	int * __percpu			pmu_disable_count;
 	struct perf_cpu_context * __percpu pmu_cpu_context;
 	int				task_ctx_nr;
@@ -901,7 +904,7 @@ struct perf_output_handle {
 
 #ifdef CONFIG_PERF_EVENTS
 
-extern int perf_pmu_register(struct pmu *pmu);
+extern int perf_pmu_register(struct pmu *pmu, char *name, int type);
 extern void perf_pmu_unregister(struct pmu *pmu);
 
 extern int perf_num_counters(void);
Index: linux-2.6/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/kernel/perf_event.c
+++ linux-2.6/kernel/perf_event.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
+#include <linux/idr.h>
 #include <linux/file.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -4804,7 +4805,7 @@ static struct pmu perf_tracepoint = {
 
 static __init int perf_tp_init(void)
 {
-	perf_pmu_register(&perf_tracepoint);
+	perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
 	return 0;
 }
 early_initcall(perf_tp_init);
@@ -5111,6 +5112,8 @@ static void *find_pmu_context(int ctxn)
 	return NULL;
 }
 
+static struct idr pmu_idr;
+
 static void free_pmu_context(void * __percpu cpu_context)
 {
 	struct pmu *pmu;
@@ -5129,7 +5132,7 @@ static void free_pmu_context(void * __pe
 	mutex_unlock(&pmus_lock);
 }
 
-int perf_pmu_register(struct pmu *pmu)
+int perf_pmu_register(struct pmu *pmu, char *name, int type)
 {
 	int cpu, ret;
 
@@ -5139,13 +5142,32 @@ int perf_pmu_register(struct pmu *pmu)
 	if (!pmu->pmu_disable_count)
 		goto unlock;
 
+	pmu->type = -1;
+	if (!name)
+		goto skip_type;
+	pmu->name = name;
+
+	if (type < 0) {
+		int err = idr_pre_get(&pmu_idr, GFP_KERNEL);
+		if (!err)
+			goto free_pdc;
+
+		err = idr_get_new_above(&pmu_idr, pmu, PERF_TYPE_MAX, &type);
+		if (err) {
+			ret = err;
+			goto free_pdc;
+		}
+	}
+	pmu->type = type;
+
+skip_type:
 	pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
 	if (pmu->pmu_cpu_context)
 		goto got_cpu_context;
 
 	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
 	if (!pmu->pmu_cpu_context)
-		goto free_pdc;
+		goto free_ird;
 
 	for_each_possible_cpu(cpu) {
 		struct perf_cpu_context *cpuctx;
@@ -5188,6 +5210,10 @@ int perf_pmu_register(struct pmu *pmu)
 
 	return ret;
 
+free_idr:
+	if (pmu->type >= PERF_TYPE_MAX)
+		idr_remove(&pmu_idr, pmu->type);
+
 free_pdc:
 	free_percpu(pmu->pmu_disable_count);
 	goto unlock;
@@ -5207,6 +5233,8 @@ void perf_pmu_unregister(struct pmu *pmu
 	synchronize_rcu();
 
 	free_percpu(pmu->pmu_disable_count);
+	if (pmu->type >= PERF_TYPE_MAX)
+		idr_remove(&pmu_idr, pmu->type);
 	free_pmu_context(pmu->pmu_cpu_context);
 }
 
@@ -5216,6 +5244,13 @@ struct pmu *perf_init_event(struct perf_
 	int idx;
 
 	idx = srcu_read_lock(&pmus_srcu);
+
+	rcu_read_lock();
+	pmu = idr_find(&pmu_idr, event->attr.type);
+	rcu_read_unlock();
+	if (pmu)
+		goto unlock;
+
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		int ret = pmu->event_init(event);
 		if (!ret)
@@ -6319,10 +6354,12 @@ perf_cpu_notify(struct notifier_block *s
 
 void __init perf_event_init(void)
 {
+	idr_init(&pmu_idr);
+
 	perf_event_init_all_cpus();
 	init_srcu_struct(&pmus_srcu);
-	perf_pmu_register(&perf_swevent);
-	perf_pmu_register(&perf_cpu_clock);
-	perf_pmu_register(&perf_task_clock);
+	perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);
+	perf_pmu_register(&perf_cpu_clock, NULL, -1);
+	perf_pmu_register(&perf_task_clock, NULL, -1);
 	perf_cpu_notifier(perf_cpu_notify);
 }
Index: linux-2.6/arch/alpha/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/perf_event.c
+++ linux-2.6/arch/alpha/kernel/perf_event.c
@@ -882,7 +882,7 @@ int __init init_hw_perf_events(void)
 	/* And set up PMU specification */
 	alpha_pmu = &ev67_pmu;
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
Index: linux-2.6/arch/arm/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/perf_event.c
+++ linux-2.6/arch/arm/kernel/perf_event.c
@@ -3034,7 +3034,7 @@ init_hw_perf_events(void)
 		pr_info("no hardware support available\n");
 	}
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
Index: linux-2.6/arch/powerpc/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/perf_event.c
+++ linux-2.6/arch/powerpc/kernel/perf_event.c
@@ -1379,7 +1379,7 @@ int register_power_pmu(struct power_pmu 
 		freeze_events_kernel = MMCR0_FCHV;
 #endif /* CONFIG_PPC64 */
 
-	perf_pmu_register(&power_pmu);
+	perf_pmu_register(&power_pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(power_pmu_notifier);
 
 	return 0;
Index: linux-2.6/arch/powerpc/kernel/perf_event_fsl_emb.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ linux-2.6/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -681,7 +681,7 @@ int register_fsl_emb_pmu(struct fsl_emb_
 	pr_info("%s performance monitor hardware support registered\n",
 		pmu->name);
 
-	perf_pmu_register(&fsl_emb_pmu);
+	perf_pmu_register(&fsl_emb_pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
Index: linux-2.6/arch/sh/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/perf_event.c
+++ linux-2.6/arch/sh/kernel/perf_event.c
@@ -389,7 +389,7 @@ int __cpuinit register_sh_pmu(struct sh_
 
 	WARN_ON(_pmu->num_events > MAX_HWEVENTS);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(sh_pmu_notifier);
 	return 0;
 }
Index: linux-2.6/arch/sparc/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/perf_event.c
+++ linux-2.6/arch/sparc/kernel/perf_event.c
@@ -1318,7 +1318,7 @@ int __init init_hw_perf_events(void)
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	register_die_notifier(&perf_event_nmi_notifier);
 
 	return 0;
Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c
+++ linux-2.6/arch/x86/kernel/cpu/perf_event.c
@@ -1418,7 +1418,7 @@ int __init init_hw_perf_events(void)
 	pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
 	pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(x86_pmu_notifier);
 
 	return 0;
Index: linux-2.6/kernel/hw_breakpoint.c
===================================================================
--- linux-2.6.orig/kernel/hw_breakpoint.c
+++ linux-2.6/kernel/hw_breakpoint.c
@@ -641,7 +641,7 @@ static int __init init_hw_breakpoint(voi
 
 	constraints_initialized = 1;
 
-	perf_pmu_register(&perf_breakpoint);
+	perf_pmu_register(&perf_breakpoint, "breakpoint", PERF_TYPE_BREAKPOINT);
 
 	return register_die_notifier(&hw_breakpoint_exceptions_nb);
 



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 7/8] perf: Sysfs enumeration
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
                   ` (5 preceding siblings ...)
  2010-11-17 22:17 ` [RFC][PATCH 6/8] perf: Dynamic pmu types Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  2010-12-16 12:33   ` [tip:perf/core] " tip-bot for Peter Zijlstra
  2010-11-17 22:17 ` [RFC][PATCH 8/8] perf: Sysfs events Peter Zijlstra
  7 siblings, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-sysfs.patch --]
[-- Type: text/plain, Size: 4222 bytes --]

Simple sysfs emumeration of the PMUs.

Use a "event_source" bus, and add PMU devices using their name.

Each PMU device has a type attribute which contrains the value needed
for perf_event_attr::type to identify this PMU.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 include/linux/perf_event.h |    1 
 kernel/perf_event.c        |   94 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 94 insertions(+), 1 deletion(-)

Index: linux-2.6/include/linux/perf_event.h
===================================================================
--- linux-2.6.orig/include/linux/perf_event.h
+++ linux-2.6/include/linux/perf_event.h
@@ -578,6 +578,7 @@ struct perf_event;
 struct pmu {
 	struct list_head		entry;
 
+	struct device			*dev;
 	char				*name;
 	int				type;
 
Index: linux-2.6/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/kernel/perf_event.c
+++ linux-2.6/kernel/perf_event.c
@@ -23,6 +23,7 @@
 #include <linux/percpu.h>
 #include <linux/ptrace.h>
 #include <linux/vmstat.h>
+#include <linux/device.h>
 #include <linux/vmalloc.h>
 #include <linux/hardirq.h>
 #include <linux/rculist.h>
@@ -5112,7 +5113,25 @@ static void *find_pmu_context(int ctxn)
 	return NULL;
 }
 
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *page)
+{
+	struct pmu *pmu = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
+}
+
+static struct device_attribute pmu_dev_attrs[] = {
+       __ATTR_RO(type),
+       __ATTR_NULL,
+};
+
 static struct idr pmu_idr;
+static int pmu_bus_running;
+static struct bus_type pmu_bus = {
+	.name		= "event_source",
+	.dev_attrs	= pmu_dev_attrs,
+};
 
 static void free_pmu_context(void * __percpu cpu_context)
 {
@@ -5132,6 +5151,39 @@ static void free_pmu_context(void * __pe
 	mutex_unlock(&pmus_lock);
 }
 
+static void pmu_dev_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+static int pmu_dev_alloc(struct pmu *pmu)
+{
+	int ret = -ENOMEM;
+
+	pmu->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+	if (!pmu->dev)
+		goto out;
+
+	device_initialize(pmu->dev);
+	ret = dev_set_name(pmu->dev, "%s", pmu->name);
+	if (ret)
+		goto free_dev;
+
+	dev_set_drvdata(pmu->dev, pmu);
+	pmu->dev->bus = &pmu_bus;
+	pmu->dev->release = pmu_dev_release;
+	ret = device_add(pmu->dev);
+	if (ret)
+		goto free_dev;
+
+out:
+	return ret;
+
+free_dev:
+	put_device(pmu->dev);
+	goto out;
+}
+
 int perf_pmu_register(struct pmu *pmu, char *name, int type)
 {
 	int cpu, ret;
@@ -5160,6 +5212,12 @@ int perf_pmu_register(struct pmu *pmu, c
 	}
 	pmu->type = type;
 
+	if (pmu_bus_running) {
+		ret = pmu_dev_alloc(pmu);
+		if (ret)
+			goto free_idr;
+	}
+
 skip_type:
 	pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
 	if (pmu->pmu_cpu_context)
@@ -5167,7 +5225,7 @@ int perf_pmu_register(struct pmu *pmu, c
 
 	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
 	if (!pmu->pmu_cpu_context)
-		goto free_ird;
+		goto free_dev;
 
 	for_each_possible_cpu(cpu) {
 		struct perf_cpu_context *cpuctx;
@@ -5210,6 +5268,10 @@ int perf_pmu_register(struct pmu *pmu, c
 
 	return ret;
 
+free_dev:
+	device_del(pmu->dev);
+	put_device(pmu->dev);
+
 free_idr:
 	if (pmu->type >= PERF_TYPE_MAX)
 		idr_remove(&pmu_idr, pmu->type);
@@ -5235,6 +5297,8 @@ void perf_pmu_unregister(struct pmu *pmu
 	free_percpu(pmu->pmu_disable_count);
 	if (pmu->type >= PERF_TYPE_MAX)
 		idr_remove(&pmu_idr, pmu->type);
+	device_del(pmu->dev);
+	put_device(pmu->dev);
 	free_pmu_context(pmu->pmu_cpu_context);
 }
 
@@ -6363,3 +6427,31 @@ void __init perf_event_init(void)
 	perf_pmu_register(&perf_task_clock, NULL, -1);
 	perf_cpu_notifier(perf_cpu_notify);
 }
+
+static int __init perf_event_sysfs_init(void)
+{
+	struct pmu *pmu;
+	int ret;
+
+	mutex_lock(&pmus_lock);
+
+	ret = bus_register(&pmu_bus);
+	if (ret)
+		goto unlock;
+
+	list_for_each_entry(pmu, &pmus, entry) {
+		if (!pmu->name || pmu->type < 0)
+			continue;
+
+		ret = pmu_dev_alloc(pmu);
+		WARN(ret, "Failed to register pmu: %s, reason %d\n", pmu->name, ret);
+	}
+	pmu_bus_running = 1;
+	ret = 0;
+
+unlock:
+	mutex_unlock(&pmus_lock);
+
+	return ret;
+}
+__initcall(perf_event_sysfs_init);



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC][PATCH 8/8] perf: Sysfs events
  2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
                   ` (6 preceding siblings ...)
  2010-11-17 22:17 ` [RFC][PATCH 7/8] perf: Sysfs enumeration Peter Zijlstra
@ 2010-11-17 22:17 ` Peter Zijlstra
  7 siblings, 0 replies; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-17 22:17 UTC (permalink / raw)
  To: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett
  Cc: linux-kernel, Peter Zijlstra

[-- Attachment #1: perf-sysfs-events.patch --]
[-- Type: text/plain, Size: 4531 bytes --]

Simple example of a static event enumeration,.. need to come up with
something more dynamic for things like trace-events which can come
and go during the life-time of a struct pmu.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 arch/x86/kernel/cpu/perf_event.c |   51 ++++++++++++++++++++++++++++++++++++
 include/linux/perf_event.h       |    1 
 kernel/perf_event.c              |   55 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)

Index: linux-2.6/include/linux/perf_event.h
===================================================================
--- linux-2.6.orig/include/linux/perf_event.h
+++ linux-2.6/include/linux/perf_event.h
@@ -578,6 +578,7 @@ struct perf_event;
 struct pmu {
 	struct list_head		entry;
 
+	const struct attribute_group	**groups;
 	struct device			*dev;
 	char				*name;
 	int				type;
Index: linux-2.6/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/kernel/perf_event.c
+++ linux-2.6/kernel/perf_event.c
@@ -4700,7 +4700,61 @@ static int perf_swevent_init(struct perf
 	return 0;
 }
 
+static struct attribute *swevent_attrs[PERF_COUNT_SW_MAX+1];
+
+static ssize_t swevent_attr_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	int i;
+
+	for (i = 0; swevent_attrs[i]; i++) {
+		if ((struct attribute *)attr == swevent_attrs[i])
+			break;
+	}
+
+	return snprintf(buf, PAGE_SIZE-1, "%d\n", i);
+}
+
+#define SWEVENT_ATTR(name)	\
+	static DEVICE_ATTR(name, S_IRUGO, swevent_attr_show, NULL)
+
+SWEVENT_ATTR(cpu_clock);
+SWEVENT_ATTR(task_clock);
+SWEVENT_ATTR(page_faults);
+SWEVENT_ATTR(context_switches);
+SWEVENT_ATTR(cpu_migrations);
+SWEVENT_ATTR(page_faults_min);
+SWEVENT_ATTR(page_faults_maj);
+SWEVENT_ATTR(alignment_faults);
+SWEVENT_ATTR(emulation_faults);
+
+static struct attribute *swevent_attrs[] = {
+	&dev_attr_cpu_clock.attr,
+	&dev_attr_task_clock.attr,
+	&dev_attr_page_faults.attr,
+	&dev_attr_context_switches.attr,
+	&dev_attr_cpu_migrations.attr,
+	&dev_attr_page_faults_min.attr,
+	&dev_attr_page_faults_maj.attr,
+	&dev_attr_alignment_faults.attr,
+	&dev_attr_emulation_faults.attr,
+	NULL,
+};
+
+static struct attribute_group swevent_group = {
+	.name	= "events",
+	.attrs	= swevent_attrs,
+};
+
+static const struct attribute_group *swevent_groups[] = {
+	&swevent_group,
+	NULL
+};
+
 static struct pmu perf_swevent = {
+	.groups		= swevent_groups,
+
 	.task_ctx_nr	= perf_sw_context,
 
 	.event_init	= perf_swevent_init,
@@ -5172,6 +5226,7 @@ static int pmu_dev_alloc(struct pmu *pmu
 	dev_set_drvdata(pmu->dev, pmu);
 	pmu->dev->bus = &pmu_bus;
 	pmu->dev->release = pmu_dev_release;
+	pmu->dev->groups = pmu->groups;
 	ret = device_add(pmu->dev);
 	if (ret)
 		goto free_dev;
Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c
+++ linux-2.6/arch/x86/kernel/cpu/perf_event.c
@@ -25,6 +25,7 @@
 #include <linux/highmem.h>
 #include <linux/cpu.h>
 #include <linux/bitops.h>
+#include <linux/device.h>
 
 #include <asm/apic.h>
 #include <asm/stacktrace.h>
@@ -1607,7 +1608,57 @@ int x86_pmu_event_init(struct perf_event
 	return err;
 }
 
+static struct attribute *hwevent_attrs[PERF_COUNT_HW_MAX+1];
+
+static ssize_t hwevent_attr_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	int i;
+
+	for (i = 0; hwevent_attrs[i]; i++) {
+		if ((struct attribute *)attr == hwevent_attrs[i])
+			break;
+	}
+
+	return snprintf(buf, PAGE_SIZE-1, "0x%Lx\n", x86_pmu.event_map(i));
+}
+
+#define HWEVENT_ATTR(name)	\
+	static DEVICE_ATTR(name, S_IRUGO, hwevent_attr_show, NULL)
+
+HWEVENT_ATTR(cpu_cycles);
+HWEVENT_ATTR(instructions);
+HWEVENT_ATTR(cache_references);
+HWEVENT_ATTR(cache_misses);
+HWEVENT_ATTR(branch_instructions);
+HWEVENT_ATTR(branch_misses);
+HWEVENT_ATTR(bus_cycles);
+
+static struct attribute *hwevent_attrs[] = {
+	&dev_attr_cpu_cycles.attr,
+	&dev_attr_instructions.attr,
+	&dev_attr_cache_references.attr,
+	&dev_attr_cache_misses.attr,
+	&dev_attr_branch_instructions.attr,
+	&dev_attr_branch_misses.attr,
+	&dev_attr_bus_cycles.attr,
+	NULL,
+};
+
+static struct attribute_group hwevent_group = {
+	.name	= "events",
+	.attrs	= hwevent_attrs,
+};
+
+static const struct attribute_group *hwevent_groups[] = {
+	&hwevent_group,
+	NULL
+};
+
 static struct pmu pmu = {
+	.groups		= hwevent_groups,
+
 	.pmu_enable	= x86_pmu_enable,
 	.pmu_disable	= x86_pmu_disable,
 



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-17 22:17 ` [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations Peter Zijlstra
@ 2010-11-25 10:25   ` Peter Zijlstra
  2010-11-25 14:47     ` Peter Zijlstra
  2010-11-25 17:55     ` Peter Zijlstra
  0 siblings, 2 replies; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-25 10:25 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Lin Ming, Stephane Eranian, robert.richter, Corey Ashford,
	fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, paulus, Will Deacon, Paul Mundt, Don Zickus

On Wed, 2010-11-17 at 23:17 +0100, Peter Zijlstra wrote:
> plain text document attachment (perf-fix-hw-init.patch)
> Currently architectures use various random locations to init the PMU
> driver, for some this happens before the perf core code is
> initialized.
> 
> In order to avoid calling perf_pmu_register() before the core code is
> up and running and able to deal with it, move all arch init to at
> least early_initcall (some archs use a later init, which is fine).
> 
> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> ---

<snip alpha,sparc bits>

> Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c
> +++ linux-2.6/arch/x86/kernel/cpu/perf_event.c
> @@ -1348,7 +1348,7 @@ static void __init pmu_check_apic(void)
>  	pr_info("no hardware sampling interrupt available.\n");
>  }
>  
> -void __init init_hw_perf_events(void)
> +int __init init_hw_perf_events(void)
>  {
>  	struct event_constraint *c;
>  	int err;
> @@ -1363,11 +1363,11 @@ void __init init_hw_perf_events(void)
>  		err = amd_pmu_init();
>  		break;
>  	default:
> -		return;
> +		return 0;
>  	}
>  	if (err != 0) {
>  		pr_cont("no PMU driver, software events only.\n");
> -		return;
> +		return 0;
>  	}
>  
>  	pmu_check_apic();
> @@ -1420,7 +1420,10 @@ void __init init_hw_perf_events(void)
>  
>  	perf_pmu_register(&pmu);
>  	perf_cpu_notifier(x86_pmu_notifier);
> +
> +	return 0;
>  }
> +early_initcall(init_hw_perf_events);
>  
>  static inline void x86_pmu_read(struct perf_event *event)
>  {

Right, so hw perf init happens from (after this patch):

 arch_initcall: powerpc, arm, sh, mips
 early_initcall: x86, sparc, alpha


Now the problem is that the generic watchdog code (kernel/watchdog.c)
tries to create hw perf events, and that too runs from early_initcall.

So my question is, how do we go about curing this, because powerpc, arm,
sh and mips are too late and the rest depends on link order to work, not
really a nice situation.

There's two categories of solutions:
 - move the watchdog later, and
 - move the hw perf init earlier.

The former is undesired because we want the watchdog as early as
possible, the later needs new infrastructure (also, I don't know if the
arch implementations can actually run this early).

So do I create a perf_initcall() or is there another solution that
avoids things like calling the watchdog code from all arch init code?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-25 10:25   ` Peter Zijlstra
@ 2010-11-25 14:47     ` Peter Zijlstra
  2010-11-25 16:22       ` Will Deacon
  2010-11-25 17:55     ` Peter Zijlstra
  1 sibling, 1 reply; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-25 14:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Lin Ming, Stephane Eranian, robert.richter, Corey Ashford,
	fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, Will Deacon, Paul Mundt, Don Zickus

[-- Attachment #1: Type: text/plain, Size: 1386 bytes --]

On Thu, 2010-11-25 at 11:25 +0100, Peter Zijlstra wrote:
> 
> Right, so hw perf init happens from (after this patch):
> 
>  arch_initcall: powerpc, arm, sh, mips
>  early_initcall: x86, sparc, alpha
> 
> 
> Now the problem is that the generic watchdog code (kernel/watchdog.c)
> tries to create hw perf events, and that too runs from early_initcall.
> 
> So my question is, how do we go about curing this, because powerpc, arm,
> sh and mips are too late and the rest depends on link order to work, not
> really a nice situation.
> 
> There's two categories of solutions:
>  - move the watchdog later, and
>  - move the hw perf init earlier.
> 
> The former is undesired because we want the watchdog as early as
> possible, the later needs new infrastructure (also, I don't know if the
> arch implementations can actually run this early).
> 
> So do I create a perf_initcall() or is there another solution that
> avoids things like calling the watchdog code from all arch init code? 

How about something like these? After this we could even look at making
the watchdog code an explicit init in main.c right after
do_perf_initcalls() (or later if it requires more to be up and running).



Hrm,. except that it all builds but doesn't seem to actually work, I
guess I need more magics to make the perf_initcall() thing work.

/me goes investigate



[-- Attachment #2: perf_initcall.patch --]
[-- Type: text/x-patch, Size: 3856 bytes --]

Subject: perf, core: Introduce perf_initcall()
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
Date: Thu Nov 25 15:27:49 CET 2010

In order to initialize the built-in hardware PMU drivers before
early_initcall() -- which is used by the watchdog code and expects the
hardware PMUs to be present.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <new-submission>
---
 include/asm-generic/vmlinux.lds.h |    2 +
 include/linux/init.h              |    7 +++++
 init/main.c                       |   53 ++++++++++++++++++++++----------------
 3 files changed, 40 insertions(+), 22 deletions(-)

Index: linux-2.6/include/asm-generic/vmlinux.lds.h
===================================================================
--- linux-2.6.orig/include/asm-generic/vmlinux.lds.h
+++ linux-2.6/include/asm-generic/vmlinux.lds.h
@@ -600,6 +600,8 @@
 		VMLINUX_SYMBOL(__setup_end) = .;
 
 #define INITCALLS							\
+	*(.initcallperf.init)						\
+	VMLINUX_SYMBOL(__perf_initcall_end) = .;			\
 	*(.initcallearly.init)						\
 	VMLINUX_SYMBOL(__early_initcall_end) = .;			\
   	*(.initcall0.init)						\
Index: linux-2.6/include/linux/init.h
===================================================================
--- linux-2.6.orig/include/linux/init.h
+++ linux-2.6/include/linux/init.h
@@ -179,6 +179,13 @@ extern int initcall_debug;
 	__attribute__((__section__(".initcall" level ".init"))) = fn
 
 /*
+ * Very early initcalls, run after the perf core is up.
+ *
+ * Only for build-in code, not modules.
+ */
+#define perf_initcall(fn)		__define_initcall("perf",fn,perf)
+
+/*
  * Early initcalls run before initializing SMP.
  *
  * Only for built-in code, not modules.
Index: linux-2.6/init/main.c
===================================================================
--- linux-2.6.orig/init/main.c
+++ linux-2.6/init/main.c
@@ -515,6 +515,36 @@ void __init __weak thread_info_cache_ini
 {
 }
 
+extern initcall_t __initcall_start[], __initcall_end[],
+		  __perf_initcall_end[], __early_initcall_end[];
+
+static void __init do_perf_initcalls(void)
+{
+	initcall_t *fn;
+
+	for (fn = __initcall_start; fn < __perf_initcall_end; fn++)
+		do_one_initcall(*fn);
+}
+
+static void __init do_pre_smp_initcalls(void)
+{
+	initcall_t *fn;
+
+	for (fn = __perf_initcall_end; fn < __early_initcall_end; fn++)
+		do_one_initcall(*fn);
+}
+
+static void __init do_initcalls(void)
+{
+	initcall_t *fn;
+
+	for (fn = __early_initcall_end; fn < __initcall_end; fn++)
+		do_one_initcall(*fn);
+
+	/* Make sure there is no pending stuff from the initcall sequence */
+	flush_scheduled_work();
+}
+
 /*
  * Set up kernel memory allocators
  */
@@ -605,6 +635,7 @@ asmlinkage void __init start_kernel(void
 		local_irq_disable();
 	}
 	perf_event_init();
+	do_perf_initcalls();
 	rcu_init();
 	radix_tree_init();
 	/* init some links before init_ISA_irqs() */
@@ -768,20 +799,6 @@ int __init_or_module do_one_initcall(ini
 	return ret;
 }
 
-
-extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
-
-static void __init do_initcalls(void)
-{
-	initcall_t *fn;
-
-	for (fn = __early_initcall_end; fn < __initcall_end; fn++)
-		do_one_initcall(*fn);
-
-	/* Make sure there is no pending stuff from the initcall sequence */
-	flush_scheduled_work();
-}
-
 /*
  * Ok, the machine is now initialized. None of the devices
  * have been touched yet, but the CPU subsystem is up and
@@ -800,14 +817,6 @@ static void __init do_basic_setup(void)
 	do_initcalls();
 }
 
-static void __init do_pre_smp_initcalls(void)
-{
-	initcall_t *fn;
-
-	for (fn = __initcall_start; fn < __early_initcall_end; fn++)
-		do_one_initcall(*fn);
-}
-
 static void run_init_process(const char *init_filename)
 {
 	argv_init[0] = init_filename;

[-- Attachment #3: perf-fix-hw-init.patch --]
[-- Type: text/x-patch, Size: 12783 bytes --]

Subject: perf, arch: Use perf_initcall() for all arch pmu implementations
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
Date: Tue Nov 16 22:08:28 CET 2010

Currently architectures use various random locations to init the PMU
driver, for some this happens before the perf core code is
initialized.

In order to avoid calling perf_pmu_register() before the core code is
up and running and able to deal with it, move all arch pmu init calls
to perf_initcall().

Cc: Michael Cree <mcree@orcon.net.nz>
Cc: David Miller <davem@davemloft.net>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: paulus <paulus@samba.org>
Cc: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101117222056.040309789@chello.nl>
---
 arch/alpha/include/asm/perf_event.h  |    6 ------
 arch/alpha/kernel/irq_alpha.c        |    2 --
 arch/alpha/kernel/perf_event.c       |    9 ++++++---
 arch/arm/kernel/perf_event.c         |    2 +-
 arch/mips/kernel/perf_event_mipsxx.c |    2 +-
 arch/powerpc/kernel/e500-pmu.c       |    2 +-
 arch/powerpc/kernel/mpc7450-pmu.c    |    2 +-
 arch/powerpc/kernel/power4-pmu.c     |    2 +-
 arch/powerpc/kernel/power5+-pmu.c    |    2 +-
 arch/powerpc/kernel/power5-pmu.c     |    2 +-
 arch/powerpc/kernel/power6-pmu.c     |    2 +-
 arch/powerpc/kernel/power7-pmu.c     |    2 +-
 arch/powerpc/kernel/ppc970-pmu.c     |    2 +-
 arch/sh/kernel/cpu/sh4/perf_event.c  |    2 +-
 arch/sh/kernel/cpu/sh4a/perf_event.c |    2 +-
 arch/sparc/include/asm/perf_event.h  |    4 ----
 arch/sparc/kernel/nmi.c              |    2 --
 arch/sparc/kernel/perf_event.c       |    7 +++++--
 arch/x86/include/asm/perf_event.h    |    2 --
 arch/x86/kernel/cpu/common.c         |    1 -
 arch/x86/kernel/cpu/perf_event.c     |   11 +++++++----
 21 files changed, 30 insertions(+), 38 deletions(-)

Index: linux-2.6/arch/alpha/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/alpha/include/asm/perf_event.h
+++ linux-2.6/arch/alpha/include/asm/perf_event.h
@@ -1,10 +1,4 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-#ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
-#else
-static inline void init_hw_perf_events(void)    { }
-#endif
-
 #endif /* __ASM_ALPHA_PERF_EVENT_H */
Index: linux-2.6/arch/alpha/kernel/irq_alpha.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_alpha.c
+++ linux-2.6/arch/alpha/kernel/irq_alpha.c
@@ -112,8 +112,6 @@ init_IRQ(void)
 	wrent(entInt, 0);
 
 	alpha_mv.init_irq();
-
-	init_hw_perf_events();
 }
 
 /*
Index: linux-2.6/arch/alpha/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/perf_event.c
+++ linux-2.6/arch/alpha/kernel/perf_event.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
+#include <linux/init.h>
 
 #include <asm/hwrpb.h>
 #include <asm/atomic.h>
@@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler
 /*
  * Init call to initialise performance events at kernel startup.
  */
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_cpu()) {
 		pr_cont("No support for your CPU.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported CPU type!\n");
@@ -882,5 +883,7 @@ void __init init_hw_perf_events(void)
 	alpha_pmu = &ev67_pmu;
 
 	perf_pmu_register(&pmu);
-}
 
+	return 0;
+}
+perf_initcall(init_hw_perf_events);
Index: linux-2.6/arch/sparc/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/sparc/include/asm/perf_event.h
+++ linux-2.6/arch/sparc/include/asm/perf_event.h
@@ -4,8 +4,6 @@
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
-extern void init_hw_perf_events(void);
-
 #define perf_arch_fetch_caller_regs(regs, ip)		\
 do {							\
 	unsigned long _pstate, _asi, _pil, _i7, _fp;	\
@@ -26,8 +24,6 @@ do {							\
 	(regs)->u_regs[UREG_I6] = _fp;			\
 	(regs)->u_regs[UREG_I7] = _i7;			\
 } while (0)
-#else
-static inline void init_hw_perf_events(void)	{ }
 #endif
 
 #endif
Index: linux-2.6/arch/sparc/kernel/nmi.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/nmi.c
+++ linux-2.6/arch/sparc/kernel/nmi.c
@@ -270,8 +270,6 @@ int __init nmi_init(void)
 			atomic_set(&nmi_active, -1);
 		}
 	}
-	if (!err)
-		init_hw_perf_events();
 
 	return err;
 }
Index: linux-2.6/arch/sparc/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/perf_event.c
+++ linux-2.6/arch/sparc/kernel/perf_event.c
@@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void)
 	return false;
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
 	perf_pmu_register(&pmu);
 	register_die_notifier(&perf_event_nmi_notifier);
+
+	return 0;
 }
+perf_initcall(init_hw_perf_event);
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
Index: linux-2.6/arch/x86/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/perf_event.h
+++ linux-2.6/arch/x86/include/asm/perf_event.h
@@ -125,7 +125,6 @@ union cpuid10_edx {
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
 #ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
 extern void perf_events_lapic_init(void);
 
 #define PERF_EVENT_INDEX_OFFSET			0
@@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(str
 }
 
 #else
-static inline void init_hw_perf_events(void)		{ }
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
Index: linux-2.6/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6/arch/x86/kernel/cpu/common.c
@@ -894,7 +894,6 @@ void __init identify_boot_cpu(void)
 #else
 	vgetcpu_set_mode();
 #endif
-	init_hw_perf_events();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c
+++ linux-2.6/arch/x86/kernel/cpu/perf_event.c
@@ -1423,7 +1423,7 @@ static void __init pmu_check_apic(void)
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1438,11 +1438,11 @@ void __init init_hw_perf_events(void)
 		err = amd_pmu_init();
 		break;
 	default:
-		return;
+		return 0;
 	}
 	if (err != 0) {
 		pr_cont("no PMU driver, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pmu_check_apic();
@@ -1450,7 +1450,7 @@ void __init init_hw_perf_events(void)
 	/* sanity check that the hardware exists or is emulated */
 	if (!check_hw_exists()) {
 		pr_cont("Broken PMU hardware detected, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("%s PMU driver.\n", x86_pmu.name);
@@ -1501,7 +1501,10 @@ void __init init_hw_perf_events(void)
 
 	perf_pmu_register(&pmu);
 	perf_cpu_notifier(x86_pmu_notifier);
+
+	return 0;
 }
+perf_initcall(init_hw_perf_events);
 
 static inline void x86_pmu_read(struct perf_event *event)
 {
Index: linux-2.6/arch/arm/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/perf_event.c
+++ linux-2.6/arch/arm/kernel/perf_event.c
@@ -3038,7 +3038,7 @@ init_hw_perf_events(void)
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+perf_initcall(init_hw_perf_events);
 
 /*
  * Callchain handling code.
Index: linux-2.6/arch/mips/kernel/perf_event_mipsxx.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/perf_event_mipsxx.c
+++ linux-2.6/arch/mips/kernel/perf_event_mipsxx.c
@@ -1047,6 +1047,6 @@ init_hw_perf_events(void)
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+perf_initcall(init_hw_perf_events);
 
 #endif /* defined(CONFIG_CPU_MIPS32)... */
Index: linux-2.6/arch/powerpc/kernel/e500-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/e500-pmu.c
+++ linux-2.6/arch/powerpc/kernel/e500-pmu.c
@@ -126,4 +126,4 @@ static int init_e500_pmu(void)
 	return register_fsl_emb_pmu(&e500_pmu);
 }
 
-arch_initcall(init_e500_pmu);
+perf_initcall(init_e500_pmu);
Index: linux-2.6/arch/powerpc/kernel/mpc7450-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/mpc7450-pmu.c
+++ linux-2.6/arch/powerpc/kernel/mpc7450-pmu.c
@@ -414,4 +414,4 @@ static int init_mpc7450_pmu(void)
 	return register_power_pmu(&mpc7450_pmu);
 }
 
-arch_initcall(init_mpc7450_pmu);
+perf_initcall(init_mpc7450_pmu);
Index: linux-2.6/arch/powerpc/kernel/power4-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power4-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power4-pmu.c
@@ -613,4 +613,4 @@ static int init_power4_pmu(void)
 	return register_power_pmu(&power4_pmu);
 }
 
-arch_initcall(init_power4_pmu);
+perf_initcall(init_power4_pmu);
Index: linux-2.6/arch/powerpc/kernel/power5+-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power5+-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power5+-pmu.c
@@ -682,4 +682,4 @@ static int init_power5p_pmu(void)
 	return register_power_pmu(&power5p_pmu);
 }
 
-arch_initcall(init_power5p_pmu);
+perf_initcall(init_power5p_pmu);
Index: linux-2.6/arch/powerpc/kernel/power5-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power5-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power5-pmu.c
@@ -621,4 +621,4 @@ static int init_power5_pmu(void)
 	return register_power_pmu(&power5_pmu);
 }
 
-arch_initcall(init_power5_pmu);
+perf_initcall(init_power5_pmu);
Index: linux-2.6/arch/powerpc/kernel/power6-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power6-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power6-pmu.c
@@ -544,4 +544,4 @@ static int init_power6_pmu(void)
 	return register_power_pmu(&power6_pmu);
 }
 
-arch_initcall(init_power6_pmu);
+perf_initcall(init_power6_pmu);
Index: linux-2.6/arch/powerpc/kernel/power7-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power7-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power7-pmu.c
@@ -369,4 +369,4 @@ static int init_power7_pmu(void)
 	return register_power_pmu(&power7_pmu);
 }
 
-arch_initcall(init_power7_pmu);
+perf_initcall(init_power7_pmu);
Index: linux-2.6/arch/powerpc/kernel/ppc970-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/ppc970-pmu.c
+++ linux-2.6/arch/powerpc/kernel/ppc970-pmu.c
@@ -494,4 +494,4 @@ static int init_ppc970_pmu(void)
 	return register_power_pmu(&ppc970_pmu);
 }
 
-arch_initcall(init_ppc970_pmu);
+perf_initcall(init_ppc970_pmu);
Index: linux-2.6/arch/sh/kernel/cpu/sh4/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/cpu/sh4/perf_event.c
+++ linux-2.6/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -250,4 +250,4 @@ static int __init sh7750_pmu_init(void)
 
 	return register_sh_pmu(&sh7750_pmu);
 }
-arch_initcall(sh7750_pmu_init);
+perf_initcall(sh7750_pmu_init);
Index: linux-2.6/arch/sh/kernel/cpu/sh4a/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/cpu/sh4a/perf_event.c
+++ linux-2.6/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -284,4 +284,4 @@ static int __init sh4a_pmu_init(void)
 
 	return register_sh_pmu(&sh4a_pmu);
 }
-arch_initcall(sh4a_pmu_init);
+perf_initcall(sh4a_pmu_init);

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-25 14:47     ` Peter Zijlstra
@ 2010-11-25 16:22       ` Will Deacon
  2010-11-25 16:34         ` Peter Zijlstra
  0 siblings, 1 reply; 22+ messages in thread
From: Will Deacon @ 2010-11-25 16:22 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, Paul Mundt, Don Zickus

Hi Peter,

On Thu, 2010-11-25 at 14:47 +0000, Peter Zijlstra wrote:
> > So do I create a perf_initcall() or is there another solution that
> > avoids things like calling the watchdog code from all arch init code?
> 
> How about something like these? After this we could even look at making
> the watchdog code an explicit init in main.c right after
> do_perf_initcalls() (or later if it requires more to be up and running).
> 
What tree/branch are these patches taken against? They don't seem
to apply against -rc3 or tip/master. Anyway, I currently have some
pending patches to split up the monolithic perf_event.c we have for ARM
so that different PMU implementations can live in different files (in
the same way that x86 does it). This might mean that your initcall patch
no longer applies because it will be a couple of thousand lines higher
up in the file.

The patches are available here:

git://linux-arm.org/linux-2.6-wd.git perf-split

I'll put these into Russell's patch system today so they should be
candidates for 2.6.38.
> 
> Hrm,. except that it all builds but doesn't seem to actually work, I
> guess I need more magics to make the perf_initcall() thing work.
> 
> /me goes investigate

Good luck!

Will




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-25 16:22       ` Will Deacon
@ 2010-11-25 16:34         ` Peter Zijlstra
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-25 16:34 UTC (permalink / raw)
  To: Will Deacon
  Cc: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, Paul Mundt, Don Zickus

On Thu, 2010-11-25 at 16:22 +0000, Will Deacon wrote:
> What tree/branch are these patches taken against? They don't seem
> to apply against -rc3 or tip/master.

tip/master + my quilt queue

>  Anyway, I currently have some
> pending patches to split up the monolithic perf_event.c we have for ARM
> so that different PMU implementations can live in different files (in
> the same way that x86 does it). This might mean that your initcall patch
> no longer applies because it will be a couple of thousand lines higher
> up in the file. 

That's ok, I'm sure we can sort that out when I've got stuff working ;-)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-25 10:25   ` Peter Zijlstra
  2010-11-25 14:47     ` Peter Zijlstra
@ 2010-11-25 17:55     ` Peter Zijlstra
  2010-11-26  7:13       ` Paul Mundt
                         ` (2 more replies)
  1 sibling, 3 replies; 22+ messages in thread
From: Peter Zijlstra @ 2010-11-25 17:55 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Lin Ming, Stephane Eranian, robert.richter, Corey Ashford,
	fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, Will Deacon, Paul Mundt, Don Zickus,
	Jason Wessel

On Thu, 2010-11-25 at 11:25 +0100, Peter Zijlstra wrote:
> 
> Right, so hw perf init happens from (after this patch):
> 
>  arch_initcall: powerpc, arm, sh, mips
>  early_initcall: x86, sparc, alpha
> 
> 
> Now the problem is that the generic watchdog code (kernel/watchdog.c)
> tries to create hw perf events, and that too runs from early_initcall.
> 
> So my question is, how do we go about curing this, because powerpc, arm,
> sh and mips are too late and the rest depends on link order to work, not
> really a nice situation.
> 
> There's two categories of solutions:
>  - move the watchdog later, and
>  - move the hw perf init earlier.
> 
> The former is undesired because we want the watchdog as early as
> possible, the later needs new infrastructure (also, I don't know if the
> arch implementations can actually run this early).
> 
> So do I create a perf_initcall() or is there another solution that
> avoids things like calling the watchdog code from all arch init code? 

So the perf_event_init() site is _waaay_ to early to init stuff.. I
guess I'll move it all to early_initcall() and I'll move the watchdog to
an explicit call right after it.

Something like the below,.. now I guess the question to all of you is,
can your arch pmu code cope with early_initcall() or does it need to be
some other place?

---
 arch/alpha/include/asm/perf_event.h  |    6 ------
 arch/alpha/kernel/irq_alpha.c        |    2 --
 arch/alpha/kernel/perf_event.c       |    9 ++++++---
 arch/arm/kernel/perf_event.c         |    2 +-
 arch/mips/kernel/perf_event_mipsxx.c |    2 +-
 arch/powerpc/kernel/e500-pmu.c       |    2 +-
 arch/powerpc/kernel/mpc7450-pmu.c    |    2 +-
 arch/powerpc/kernel/power4-pmu.c     |    2 +-
 arch/powerpc/kernel/power5+-pmu.c    |    2 +-
 arch/powerpc/kernel/power5-pmu.c     |    2 +-
 arch/powerpc/kernel/power6-pmu.c     |    2 +-
 arch/powerpc/kernel/power7-pmu.c     |    2 +-
 arch/powerpc/kernel/ppc970-pmu.c     |    2 +-
 arch/sh/kernel/cpu/sh4/perf_event.c  |    2 +-
 arch/sh/kernel/cpu/sh4a/perf_event.c |    2 +-
 arch/sparc/include/asm/perf_event.h  |    4 ----
 arch/sparc/kernel/nmi.c              |    2 --
 arch/sparc/kernel/perf_event.c       |    7 +++++--
 arch/x86/include/asm/perf_event.h    |    2 --
 arch/x86/kernel/cpu/common.c         |    1 -
 arch/x86/kernel/cpu/perf_event.c     |   11 +++++++----
 include/linux/sched.h                |    4 ++++
 init/main.c                          |    1 +
 kernel/watchdog.c                    |    7 +++----
 24 files changed, 38 insertions(+), 42 deletions(-)

Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -316,6 +316,7 @@ extern int proc_dowatchdog_thresh(struct
 				  size_t *lenp, loff_t *ppos);
 extern unsigned int  softlockup_panic;
 extern int softlockup_thresh;
+void lockup_detector_init(void);
 #else
 static inline void touch_softlockup_watchdog(void)
 {
@@ -326,6 +327,9 @@ static inline void touch_softlockup_watc
 static inline void touch_all_softlockup_watchdogs(void)
 {
 }
+static inline void lockup_detector_init(void)
+{
+}
 #endif
 
 #ifdef CONFIG_DETECT_HUNG_TASK
Index: linux-2.6/init/main.c
===================================================================
--- linux-2.6.orig/init/main.c
+++ linux-2.6/init/main.c
@@ -884,6 +884,7 @@ static int __init kernel_init(void * unu
 	smp_prepare_cpus(setup_max_cpus);
 
 	do_pre_smp_initcalls();
+	lockup_detector_init();
 
 	smp_init();
 	sched_init_smp();
Index: linux-2.6/kernel/watchdog.c
===================================================================
--- linux-2.6.orig/kernel/watchdog.c
+++ linux-2.6/kernel/watchdog.c
@@ -547,13 +547,13 @@ static struct notifier_block __cpuinitda
 	.notifier_call = cpu_callback
 };
 
-static int __init spawn_watchdog_task(void)
+void __init lockup_detector_init(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
 	int err;
 
 	if (no_watchdog)
-		return 0;
+		return;
 
 	err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
 	WARN_ON(notifier_to_errno(err));
@@ -561,6 +561,5 @@ static int __init spawn_watchdog_task(vo
 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 
-	return 0;
+	return;
 }
-early_initcall(spawn_watchdog_task);
Index: linux-2.6/arch/alpha/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/alpha/include/asm/perf_event.h
+++ linux-2.6/arch/alpha/include/asm/perf_event.h
@@ -1,10 +1,4 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-#ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
-#else
-static inline void init_hw_perf_events(void)    { }
-#endif
-
 #endif /* __ASM_ALPHA_PERF_EVENT_H */
Index: linux-2.6/arch/alpha/kernel/irq_alpha.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_alpha.c
+++ linux-2.6/arch/alpha/kernel/irq_alpha.c
@@ -112,8 +112,6 @@ init_IRQ(void)
 	wrent(entInt, 0);
 
 	alpha_mv.init_irq();
-
-	init_hw_perf_events();
 }
 
 /*
Index: linux-2.6/arch/alpha/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/perf_event.c
+++ linux-2.6/arch/alpha/kernel/perf_event.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
+#include <linux/init.h>
 
 #include <asm/hwrpb.h>
 #include <asm/atomic.h>
@@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler
 /*
  * Init call to initialise performance events at kernel startup.
  */
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_cpu()) {
 		pr_cont("No support for your CPU.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported CPU type!\n");
@@ -882,5 +883,7 @@ void __init init_hw_perf_events(void)
 	alpha_pmu = &ev67_pmu;
 
 	perf_pmu_register(&pmu);
-}
 
+	return 0;
+}
+early_initcall(init_hw_perf_events);
Index: linux-2.6/arch/arm/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/perf_event.c
+++ linux-2.6/arch/arm/kernel/perf_event.c
@@ -3038,7 +3038,7 @@ init_hw_perf_events(void)
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 /*
  * Callchain handling code.
Index: linux-2.6/arch/mips/kernel/perf_event_mipsxx.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/perf_event_mipsxx.c
+++ linux-2.6/arch/mips/kernel/perf_event_mipsxx.c
@@ -1047,6 +1047,6 @@ init_hw_perf_events(void)
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 #endif /* defined(CONFIG_CPU_MIPS32)... */
Index: linux-2.6/arch/powerpc/kernel/e500-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/e500-pmu.c
+++ linux-2.6/arch/powerpc/kernel/e500-pmu.c
@@ -126,4 +126,4 @@ static int init_e500_pmu(void)
 	return register_fsl_emb_pmu(&e500_pmu);
 }
 
-arch_initcall(init_e500_pmu);
+early_initcall(init_e500_pmu);
Index: linux-2.6/arch/powerpc/kernel/mpc7450-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/mpc7450-pmu.c
+++ linux-2.6/arch/powerpc/kernel/mpc7450-pmu.c
@@ -414,4 +414,4 @@ static int init_mpc7450_pmu(void)
 	return register_power_pmu(&mpc7450_pmu);
 }
 
-arch_initcall(init_mpc7450_pmu);
+early_initcall(init_mpc7450_pmu);
Index: linux-2.6/arch/powerpc/kernel/power4-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power4-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power4-pmu.c
@@ -613,4 +613,4 @@ static int init_power4_pmu(void)
 	return register_power_pmu(&power4_pmu);
 }
 
-arch_initcall(init_power4_pmu);
+early_initcall(init_power4_pmu);
Index: linux-2.6/arch/powerpc/kernel/power5+-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power5+-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power5+-pmu.c
@@ -682,4 +682,4 @@ static int init_power5p_pmu(void)
 	return register_power_pmu(&power5p_pmu);
 }
 
-arch_initcall(init_power5p_pmu);
+early_initcall(init_power5p_pmu);
Index: linux-2.6/arch/powerpc/kernel/power5-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power5-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power5-pmu.c
@@ -621,4 +621,4 @@ static int init_power5_pmu(void)
 	return register_power_pmu(&power5_pmu);
 }
 
-arch_initcall(init_power5_pmu);
+early_initcall(init_power5_pmu);
Index: linux-2.6/arch/powerpc/kernel/power6-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power6-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power6-pmu.c
@@ -544,4 +544,4 @@ static int init_power6_pmu(void)
 	return register_power_pmu(&power6_pmu);
 }
 
-arch_initcall(init_power6_pmu);
+early_initcall(init_power6_pmu);
Index: linux-2.6/arch/powerpc/kernel/power7-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/power7-pmu.c
+++ linux-2.6/arch/powerpc/kernel/power7-pmu.c
@@ -369,4 +369,4 @@ static int init_power7_pmu(void)
 	return register_power_pmu(&power7_pmu);
 }
 
-arch_initcall(init_power7_pmu);
+early_initcall(init_power7_pmu);
Index: linux-2.6/arch/powerpc/kernel/ppc970-pmu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/ppc970-pmu.c
+++ linux-2.6/arch/powerpc/kernel/ppc970-pmu.c
@@ -494,4 +494,4 @@ static int init_ppc970_pmu(void)
 	return register_power_pmu(&ppc970_pmu);
 }
 
-arch_initcall(init_ppc970_pmu);
+early_initcall(init_ppc970_pmu);
Index: linux-2.6/arch/sh/kernel/cpu/sh4/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/cpu/sh4/perf_event.c
+++ linux-2.6/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -250,4 +250,4 @@ static int __init sh7750_pmu_init(void)
 
 	return register_sh_pmu(&sh7750_pmu);
 }
-arch_initcall(sh7750_pmu_init);
+early_initcall(sh7750_pmu_init);
Index: linux-2.6/arch/sh/kernel/cpu/sh4a/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/cpu/sh4a/perf_event.c
+++ linux-2.6/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -284,4 +284,4 @@ static int __init sh4a_pmu_init(void)
 
 	return register_sh_pmu(&sh4a_pmu);
 }
-arch_initcall(sh4a_pmu_init);
+early_initcall(sh4a_pmu_init);
Index: linux-2.6/arch/sparc/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/sparc/include/asm/perf_event.h
+++ linux-2.6/arch/sparc/include/asm/perf_event.h
@@ -4,8 +4,6 @@
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
-extern void init_hw_perf_events(void);
-
 #define perf_arch_fetch_caller_regs(regs, ip)		\
 do {							\
 	unsigned long _pstate, _asi, _pil, _i7, _fp;	\
@@ -26,8 +24,6 @@ do {							\
 	(regs)->u_regs[UREG_I6] = _fp;			\
 	(regs)->u_regs[UREG_I7] = _i7;			\
 } while (0)
-#else
-static inline void init_hw_perf_events(void)	{ }
 #endif
 
 #endif
Index: linux-2.6/arch/sparc/kernel/nmi.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/nmi.c
+++ linux-2.6/arch/sparc/kernel/nmi.c
@@ -270,8 +270,6 @@ int __init nmi_init(void)
 			atomic_set(&nmi_active, -1);
 		}
 	}
-	if (!err)
-		init_hw_perf_events();
 
 	return err;
 }
Index: linux-2.6/arch/sparc/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/perf_event.c
+++ linux-2.6/arch/sparc/kernel/perf_event.c
@@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void)
 	return false;
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
 	perf_pmu_register(&pmu);
 	register_die_notifier(&perf_event_nmi_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_event);
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
Index: linux-2.6/arch/x86/include/asm/perf_event.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/perf_event.h
+++ linux-2.6/arch/x86/include/asm/perf_event.h
@@ -125,7 +125,6 @@ union cpuid10_edx {
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
 #ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
 extern void perf_events_lapic_init(void);
 
 #define PERF_EVENT_INDEX_OFFSET			0
@@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(str
 }
 
 #else
-static inline void init_hw_perf_events(void)		{ }
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
Index: linux-2.6/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6/arch/x86/kernel/cpu/common.c
@@ -894,7 +894,6 @@ void __init identify_boot_cpu(void)
 #else
 	vgetcpu_set_mode();
 #endif
-	init_hw_perf_events();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c
+++ linux-2.6/arch/x86/kernel/cpu/perf_event.c
@@ -1423,7 +1423,7 @@ static void __init pmu_check_apic(void)
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1438,11 +1438,11 @@ void __init init_hw_perf_events(void)
 		err = amd_pmu_init();
 		break;
 	default:
-		return;
+		return 0;
 	}
 	if (err != 0) {
 		pr_cont("no PMU driver, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pmu_check_apic();
@@ -1450,7 +1450,7 @@ void __init init_hw_perf_events(void)
 	/* sanity check that the hardware exists or is emulated */
 	if (!check_hw_exists()) {
 		pr_cont("Broken PMU hardware detected, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("%s PMU driver.\n", x86_pmu.name);
@@ -1501,7 +1501,10 @@ void __init init_hw_perf_events(void)
 
 	perf_pmu_register(&pmu);
 	perf_cpu_notifier(x86_pmu_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_events);
 
 static inline void x86_pmu_read(struct perf_event *event)
 {


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-25 17:55     ` Peter Zijlstra
@ 2010-11-26  7:13       ` Paul Mundt
  2010-11-26  9:41       ` Will Deacon
  2010-11-26 15:05       ` [tip:perf/core] perf, arch: Cleanup perf-pmu init vs lockup-detector tip-bot for Peter Zijlstra
  2 siblings, 0 replies; 22+ messages in thread
From: Paul Mundt @ 2010-11-26  7:13 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, Will Deacon, Don Zickus, Jason Wessel

On Thu, Nov 25, 2010 at 06:55:59PM +0100, Peter Zijlstra wrote:
> On Thu, 2010-11-25 at 11:25 +0100, Peter Zijlstra wrote:
> > 
> > Right, so hw perf init happens from (after this patch):
> > 
> >  arch_initcall: powerpc, arm, sh, mips
> >  early_initcall: x86, sparc, alpha
> > 
> > 
> > Now the problem is that the generic watchdog code (kernel/watchdog.c)
> > tries to create hw perf events, and that too runs from early_initcall.
> > 
> > So my question is, how do we go about curing this, because powerpc, arm,
> > sh and mips are too late and the rest depends on link order to work, not
> > really a nice situation.
> > 
> > There's two categories of solutions:
> >  - move the watchdog later, and
> >  - move the hw perf init earlier.
> > 
> > The former is undesired because we want the watchdog as early as
> > possible, the later needs new infrastructure (also, I don't know if the
> > arch implementations can actually run this early).
> > 
> > So do I create a perf_initcall() or is there another solution that
> > avoids things like calling the watchdog code from all arch init code? 
> 
> So the perf_event_init() site is _waaay_ to early to init stuff.. I
> guess I'll move it all to early_initcall() and I'll move the watchdog to
> an explicit call right after it.
> 
> Something like the below,.. now I guess the question to all of you is,
> can your arch pmu code cope with early_initcall() or does it need to be
> some other place?
> 
Any of the initcall levels are ok for SH at least. The only dependency we
have for the perf code is the clock framework, which comes up during
time_init().

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations
  2010-11-25 17:55     ` Peter Zijlstra
  2010-11-26  7:13       ` Paul Mundt
@ 2010-11-26  9:41       ` Will Deacon
  2010-11-26 15:05       ` [tip:perf/core] perf, arch: Cleanup perf-pmu init vs lockup-detector tip-bot for Peter Zijlstra
  2 siblings, 0 replies; 22+ messages in thread
From: Will Deacon @ 2010-11-26  9:41 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Lin Ming, Stephane Eranian, robert.richter,
	Corey Ashford, fweisbec, paulus, Greg Kroah-Hartman, Kay Sievers,
	H. Peter Anvin, Kyle Moffett, linux-kernel, davem, Michael Cree,
	Deng-Cheng Zhu, Paul Mundt, Don Zickus, Jason Wessel

On Thu, 2010-11-25 at 17:55 +0000, Peter Zijlstra wrote:
> So the perf_event_init() site is _waaay_ to early to init stuff.. I
> guess I'll move it all to early_initcall() and I'll move the watchdog to
> an explicit call right after it.
> 
> Something like the below,.. now I guess the question to all of you is,
> can your arch pmu code cope with early_initcall() or does it need to be
> some other place?
> 
The ARM init code basically just parses the CPUID to work out what PMU
is available, so it should be safe to call it as early as you like.

Will



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [tip:perf/core] perf, x86: Fixup Kconfig deps
  2010-11-17 22:17 ` [RFC][PATCH 1/8] perf, x86: Fixup Kconfig deps Peter Zijlstra
@ 2010-11-26 15:01   ` tip-bot for Peter Zijlstra
  0 siblings, 0 replies; 22+ messages in thread
From: tip-bot for Peter Zijlstra @ 2010-11-26 15:01 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, a.p.zijlstra, tglx, mingo

Commit-ID:  cc2067a51424dd25c10c1b1230b4222d8baec94d
Gitweb:     http://git.kernel.org/tip/cc2067a51424dd25c10c1b1230b4222d8baec94d
Author:     Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Tue, 16 Nov 2010 21:49:01 +0100
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 26 Nov 2010 15:00:58 +0100

perf, x86: Fixup Kconfig deps

This leads to a Kconfig dep inversion, x86 selects PERF_EVENT (due to
a hw_breakpoint dep) but doesn't unconditionally provide
HAVE_PERF_EVENT.

(This can cause build failures on M386/M486 kernel .config's.)

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101117222055.982965150@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e832768..e330da2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -21,7 +21,7 @@ config X86
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
-	select HAVE_PERF_EVENTS if (!M386 && !M486)
+	select HAVE_PERF_EVENTS
 	select HAVE_IRQ_WORK
 	select HAVE_IOREMAP_PROT
 	select HAVE_KPROBES

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [tip:perf/core] perf, arch: Cleanup perf-pmu init vs lockup-detector
  2010-11-25 17:55     ` Peter Zijlstra
  2010-11-26  7:13       ` Paul Mundt
  2010-11-26  9:41       ` Will Deacon
@ 2010-11-26 15:05       ` tip-bot for Peter Zijlstra
  2 siblings, 0 replies; 22+ messages in thread
From: tip-bot for Peter Zijlstra @ 2010-11-26 15:05 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, paulus, hpa, mingo, dengcheng.zhu, will.deacon,
	a.p.zijlstra, lethal, davem, tglx, mingo, mcree

Commit-ID:  004417a6d468e24399e383645c068b498eed84ad
Gitweb:     http://git.kernel.org/tip/004417a6d468e24399e383645c068b498eed84ad
Author:     Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Thu, 25 Nov 2010 18:38:29 +0100
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 26 Nov 2010 15:14:56 +0100

perf, arch: Cleanup perf-pmu init vs lockup-detector

The perf hardware pmu got initialized at various points in the boot,
some before early_initcall() some after (notably arch_initcall).

The problem is that the NMI lockup detector is ran from early_initcall()
and expects the hardware pmu to be present.

Sanitize this by moving all architecture hardware pmu implementations to
initialize at early_initcall() and move the lockup detector to an explicit
initcall right after that.

Cc: paulus <paulus@samba.org>
Cc: davem <davem@davemloft.net>
Cc: Michael Cree <mcree@orcon.net.nz>
Cc: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <1290707759.2145.119.camel@laptop>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/alpha/include/asm/perf_event.h  |    6 ------
 arch/alpha/kernel/irq_alpha.c        |    2 --
 arch/alpha/kernel/perf_event.c       |    9 ++++++---
 arch/arm/kernel/perf_event.c         |    2 +-
 arch/mips/kernel/perf_event_mipsxx.c |    2 +-
 arch/powerpc/kernel/e500-pmu.c       |    2 +-
 arch/powerpc/kernel/mpc7450-pmu.c    |    2 +-
 arch/powerpc/kernel/power4-pmu.c     |    2 +-
 arch/powerpc/kernel/power5+-pmu.c    |    2 +-
 arch/powerpc/kernel/power5-pmu.c     |    2 +-
 arch/powerpc/kernel/power6-pmu.c     |    2 +-
 arch/powerpc/kernel/power7-pmu.c     |    2 +-
 arch/powerpc/kernel/ppc970-pmu.c     |    2 +-
 arch/sh/kernel/cpu/sh4/perf_event.c  |    2 +-
 arch/sh/kernel/cpu/sh4a/perf_event.c |    2 +-
 arch/sparc/include/asm/perf_event.h  |    4 ----
 arch/sparc/kernel/nmi.c              |    2 --
 arch/sparc/kernel/perf_event.c       |    7 +++++--
 arch/x86/include/asm/perf_event.h    |    2 --
 arch/x86/kernel/cpu/common.c         |    1 -
 arch/x86/kernel/cpu/perf_event.c     |   11 +++++++----
 include/linux/sched.h                |    4 ++++
 init/main.c                          |    1 +
 kernel/watchdog.c                    |    7 +++----
 24 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
index fe792ca..5996e7a 100644
--- a/arch/alpha/include/asm/perf_event.h
+++ b/arch/alpha/include/asm/perf_event.h
@@ -1,10 +1,4 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-#ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
-#else
-static inline void init_hw_perf_events(void)    { }
-#endif
-
 #endif /* __ASM_ALPHA_PERF_EVENT_H */
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index 5f77afb..4c8bb37 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -112,8 +112,6 @@ init_IRQ(void)
 	wrent(entInt, 0);
 
 	alpha_mv.init_irq();
-
-	init_hw_perf_events();
 }
 
 /*
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 1cc4968..3283059 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
+#include <linux/init.h>
 
 #include <asm/hwrpb.h>
 #include <asm/atomic.h>
@@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
 /*
  * Init call to initialise performance events at kernel startup.
  */
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_cpu()) {
 		pr_cont("No support for your CPU.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported CPU type!\n");
@@ -882,5 +883,7 @@ void __init init_hw_perf_events(void)
 	alpha_pmu = &ev67_pmu;
 
 	perf_pmu_register(&pmu);
-}
 
+	return 0;
+}
+early_initcall(init_hw_perf_events);
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 07a5035..d45f70e 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -3038,7 +3038,7 @@ init_hw_perf_events(void)
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 /*
  * Callchain handling code.
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 5c7c6fc..183e0d2 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1047,6 +1047,6 @@ init_hw_perf_events(void)
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 #endif /* defined(CONFIG_CPU_MIPS32)... */
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
index 7c07de0..b150b51 100644
--- a/arch/powerpc/kernel/e500-pmu.c
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -126,4 +126,4 @@ static int init_e500_pmu(void)
 	return register_fsl_emb_pmu(&e500_pmu);
 }
 
-arch_initcall(init_e500_pmu);
+early_initcall(init_e500_pmu);
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c
index 09d7202..2cc5e03 100644
--- a/arch/powerpc/kernel/mpc7450-pmu.c
+++ b/arch/powerpc/kernel/mpc7450-pmu.c
@@ -414,4 +414,4 @@ static int init_mpc7450_pmu(void)
 	return register_power_pmu(&mpc7450_pmu);
 }
 
-arch_initcall(init_mpc7450_pmu);
+early_initcall(init_mpc7450_pmu);
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c
index 2a361cd..ead8b3c 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/kernel/power4-pmu.c
@@ -613,4 +613,4 @@ static int init_power4_pmu(void)
 	return register_power_pmu(&power4_pmu);
 }
 
-arch_initcall(init_power4_pmu);
+early_initcall(init_power4_pmu);
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index 199de52..eca0ac5 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -682,4 +682,4 @@ static int init_power5p_pmu(void)
 	return register_power_pmu(&power5p_pmu);
 }
 
-arch_initcall(init_power5p_pmu);
+early_initcall(init_power5p_pmu);
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index 98b6a72..d5ff0f6 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -621,4 +621,4 @@ static int init_power5_pmu(void)
 	return register_power_pmu(&power5_pmu);
 }
 
-arch_initcall(init_power5_pmu);
+early_initcall(init_power5_pmu);
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index 84a607b..3160392 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -544,4 +544,4 @@ static int init_power6_pmu(void)
 	return register_power_pmu(&power6_pmu);
 }
 
-arch_initcall(init_power6_pmu);
+early_initcall(init_power6_pmu);
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index 852f7b7..593740f 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -369,4 +369,4 @@ static int init_power7_pmu(void)
 	return register_power_pmu(&power7_pmu);
 }
 
-arch_initcall(init_power7_pmu);
+early_initcall(init_power7_pmu);
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 3fee685..9a6e093 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -494,4 +494,4 @@ static int init_ppc970_pmu(void)
 	return register_power_pmu(&ppc970_pmu);
 }
 
-arch_initcall(init_ppc970_pmu);
+early_initcall(init_ppc970_pmu);
diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c
index dbf3b4b..748955d 100644
--- a/arch/sh/kernel/cpu/sh4/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -250,4 +250,4 @@ static int __init sh7750_pmu_init(void)
 
 	return register_sh_pmu(&sh7750_pmu);
 }
-arch_initcall(sh7750_pmu_init);
+early_initcall(sh7750_pmu_init);
diff --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c
index 5802765..17e6beb 100644
--- a/arch/sh/kernel/cpu/sh4a/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -284,4 +284,4 @@ static int __init sh4a_pmu_init(void)
 
 	return register_sh_pmu(&sh4a_pmu);
 }
-arch_initcall(sh4a_pmu_init);
+early_initcall(sh4a_pmu_init);
diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h
index 6e8bfa1..4d3dbe3 100644
--- a/arch/sparc/include/asm/perf_event.h
+++ b/arch/sparc/include/asm/perf_event.h
@@ -4,8 +4,6 @@
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
-extern void init_hw_perf_events(void);
-
 #define perf_arch_fetch_caller_regs(regs, ip)		\
 do {							\
 	unsigned long _pstate, _asi, _pil, _i7, _fp;	\
@@ -26,8 +24,6 @@ do {							\
 	(regs)->u_regs[UREG_I6] = _fp;			\
 	(regs)->u_regs[UREG_I7] = _i7;			\
 } while (0)
-#else
-static inline void init_hw_perf_events(void)	{ }
 #endif
 
 #endif
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index a4bd7ba..300f810 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -270,8 +270,6 @@ int __init nmi_init(void)
 			atomic_set(&nmi_active, -1);
 		}
 	}
-	if (!err)
-		init_hw_perf_events();
 
 	return err;
 }
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 0d6deb5..75c5b12 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void)
 	return false;
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	pr_info("Performance events: ");
 
 	if (!supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
-		return;
+		return 0;
 	}
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
 	perf_pmu_register(&pmu);
 	register_die_notifier(&perf_event_nmi_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_event);
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 550e26b..d9d4dae 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -125,7 +125,6 @@ union cpuid10_edx {
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
 #ifdef CONFIG_PERF_EVENTS
-extern void init_hw_perf_events(void);
 extern void perf_events_lapic_init(void);
 
 #define PERF_EVENT_INDEX_OFFSET			0
@@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
 }
 
 #else
-static inline void init_hw_perf_events(void)		{ }
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4b68bda..1d59834 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -894,7 +894,6 @@ void __init identify_boot_cpu(void)
 #else
 	vgetcpu_set_mode();
 #endif
-	init_hw_perf_events();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index c01dfec..817d2b1 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1353,7 +1353,7 @@ static void __init pmu_check_apic(void)
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-void __init init_hw_perf_events(void)
+int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1368,11 +1368,11 @@ void __init init_hw_perf_events(void)
 		err = amd_pmu_init();
 		break;
 	default:
-		return;
+		return 0;
 	}
 	if (err != 0) {
 		pr_cont("no PMU driver, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pmu_check_apic();
@@ -1380,7 +1380,7 @@ void __init init_hw_perf_events(void)
 	/* sanity check that the hardware exists or is emulated */
 	if (!check_hw_exists()) {
 		pr_cont("Broken PMU hardware detected, software events only.\n");
-		return;
+		return 0;
 	}
 
 	pr_cont("%s PMU driver.\n", x86_pmu.name);
@@ -1431,7 +1431,10 @@ void __init init_hw_perf_events(void)
 
 	perf_pmu_register(&pmu);
 	perf_cpu_notifier(x86_pmu_notifier);
+
+	return 0;
 }
+early_initcall(init_hw_perf_events);
 
 static inline void x86_pmu_read(struct perf_event *event)
 {
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2c79e92..d2e63d1 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -316,6 +316,7 @@ extern int proc_dowatchdog_thresh(struct ctl_table *table, int write,
 				  size_t *lenp, loff_t *ppos);
 extern unsigned int  softlockup_panic;
 extern int softlockup_thresh;
+void lockup_detector_init(void);
 #else
 static inline void touch_softlockup_watchdog(void)
 {
@@ -326,6 +327,9 @@ static inline void touch_softlockup_watchdog_sync(void)
 static inline void touch_all_softlockup_watchdogs(void)
 {
 }
+static inline void lockup_detector_init(void)
+{
+}
 #endif
 
 #ifdef CONFIG_DETECT_HUNG_TASK
diff --git a/init/main.c b/init/main.c
index 8646401..261ad7b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -882,6 +882,7 @@ static int __init kernel_init(void * unused)
 	smp_prepare_cpus(setup_max_cpus);
 
 	do_pre_smp_initcalls();
+	lockup_detector_init();
 
 	smp_init();
 	sched_init_smp();
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 6e3c41a..cad4e42 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -547,13 +547,13 @@ static struct notifier_block __cpuinitdata cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
-static int __init spawn_watchdog_task(void)
+void __init lockup_detector_init(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
 	int err;
 
 	if (no_watchdog)
-		return 0;
+		return;
 
 	err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
 	WARN_ON(notifier_to_errno(err));
@@ -561,6 +561,5 @@ static int __init spawn_watchdog_task(void)
 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 
-	return 0;
+	return;
 }
-early_initcall(spawn_watchdog_task);

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [tip:perf/core] perf: Move perf_event_init() into main.c
  2010-11-17 22:17 ` [RFC][PATCH 3/8] perf: Move perf_event_init() into main.c Peter Zijlstra
@ 2010-12-16 12:32   ` tip-bot for Peter Zijlstra
  0 siblings, 0 replies; 22+ messages in thread
From: tip-bot for Peter Zijlstra @ 2010-12-16 12:32 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, a.p.zijlstra, tglx, mingo

Commit-ID:  24a24bb6ff3dc3a09bb131241be920ecc3f0e519
Gitweb:     http://git.kernel.org/tip/24a24bb6ff3dc3a09bb131241be920ecc3f0e519
Author:     Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 17 Nov 2010 23:17:33 +0100
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Thu, 16 Dec 2010 11:36:42 +0100

perf: Move perf_event_init() into main.c

Currently we call perf_event_init() from sched_init(). In order to
make it more obvious move it to the cannnonical location.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101117222056.093629821@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 init/main.c    |    2 ++
 kernel/sched.c |    2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/init/main.c b/init/main.c
index 261ad7b..559e862 100644
--- a/init/main.c
+++ b/init/main.c
@@ -67,6 +67,7 @@
 #include <linux/sfi.h>
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
+#include <linux/perf_event.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -603,6 +604,7 @@ asmlinkage void __init start_kernel(void)
 				"enabled *very* early, fixing it\n");
 		local_irq_disable();
 	}
+	perf_event_init();
 	rcu_init();
 	radix_tree_init();
 	/* init some links before init_ISA_irqs() */
diff --git a/kernel/sched.c b/kernel/sched.c
index dc91a4d..605ab1b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -8108,8 +8108,6 @@ void __init sched_init(void)
 		zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
 #endif /* SMP */
 
-	perf_event_init();
-
 	scheduler_running = 1;
 }
 

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [tip:perf/core] init: Initialized IDR earlier
  2010-11-17 22:17 ` [RFC][PATCH 5/8] init: Initialized IRD earlier Peter Zijlstra
@ 2010-12-16 12:32   ` tip-bot for Peter Zijlstra
  0 siblings, 0 replies; 22+ messages in thread
From: tip-bot for Peter Zijlstra @ 2010-12-16 12:32 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, a.p.zijlstra, tglx, mingo

Commit-ID:  9f58a205c62d0dad1df38d076324a89b1a0f1d65
Gitweb:     http://git.kernel.org/tip/9f58a205c62d0dad1df38d076324a89b1a0f1d65
Author:     Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 17 Nov 2010 23:17:35 +0100
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Thu, 16 Dec 2010 11:36:43 +0100

init: Initialized IDR earlier

perf_event_init() wants to start using IDR trees, its needs in turn
are satisfied by mm_init().

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101117222056.206992649@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 init/main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/init/main.c b/init/main.c
index 559e862..ea51770 100644
--- a/init/main.c
+++ b/init/main.c
@@ -604,6 +604,7 @@ asmlinkage void __init start_kernel(void)
 				"enabled *very* early, fixing it\n");
 		local_irq_disable();
 	}
+	idr_init_cache();
 	perf_event_init();
 	rcu_init();
 	radix_tree_init();
@@ -660,7 +661,6 @@ asmlinkage void __init start_kernel(void)
 	enable_debug_pagealloc();
 	kmemleak_init();
 	debug_objects_mem_init();
-	idr_init_cache();
 	setup_per_cpu_pageset();
 	numa_policy_init();
 	if (late_time_init)

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [tip:perf/core] perf: Dynamic pmu types
  2010-11-17 22:17 ` [RFC][PATCH 6/8] perf: Dynamic pmu types Peter Zijlstra
@ 2010-12-16 12:32   ` tip-bot for Peter Zijlstra
  0 siblings, 0 replies; 22+ messages in thread
From: tip-bot for Peter Zijlstra @ 2010-12-16 12:32 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, a.p.zijlstra, tglx, mingo

Commit-ID:  2e80a82a49c4c7eca4e35734380f28298ba5db19
Gitweb:     http://git.kernel.org/tip/2e80a82a49c4c7eca4e35734380f28298ba5db19
Author:     Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 17 Nov 2010 23:17:36 +0100
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Thu, 16 Dec 2010 11:36:43 +0100

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>
---
 arch/alpha/kernel/perf_event.c           |    2 +-
 arch/arm/kernel/perf_event.c             |    2 +-
 arch/powerpc/kernel/perf_event.c         |    2 +-
 arch/powerpc/kernel/perf_event_fsl_emb.c |    2 +-
 arch/sh/kernel/perf_event.c              |    2 +-
 arch/sparc/kernel/perf_event.c           |    2 +-
 arch/x86/kernel/cpu/perf_event.c         |    2 +-
 include/linux/perf_event.h               |    5 ++-
 kernel/hw_breakpoint.c                   |    2 +-
 kernel/perf_event.c                      |   48 ++++++++++++++++++++++++++----
 10 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 3283059..90561c4 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -882,7 +882,7 @@ int __init init_hw_perf_events(void)
 	/* And set up PMU specification */
 	alpha_pmu = &ev67_pmu;
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index d45f70e..fdfa497 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -3034,7 +3034,7 @@ init_hw_perf_events(void)
 		pr_info("no hardware support available\n");
 	}
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 3129c85..5674807 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1379,7 +1379,7 @@ int register_power_pmu(struct power_pmu *pmu)
 		freeze_events_kernel = MMCR0_FCHV;
 #endif /* CONFIG_PPC64 */
 
-	perf_pmu_register(&power_pmu);
+	perf_pmu_register(&power_pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(power_pmu_notifier);
 
 	return 0;
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
index 7ecca59..4dcf5f8 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -681,7 +681,7 @@ int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu)
 	pr_info("%s performance monitor hardware support registered\n",
 		pmu->name);
 
-	perf_pmu_register(&fsl_emb_pmu);
+	perf_pmu_register(&fsl_emb_pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
index 5a4b334..2ee21a4 100644
--- a/arch/sh/kernel/perf_event.c
+++ b/arch/sh/kernel/perf_event.c
@@ -389,7 +389,7 @@ int __cpuinit register_sh_pmu(struct sh_pmu *_pmu)
 
 	WARN_ON(_pmu->num_events > MAX_HWEVENTS);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(sh_pmu_notifier);
 	return 0;
 }
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 39348b1..7605786 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1318,7 +1318,7 @@ int __init init_hw_perf_events(void)
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	register_die_notifier(&perf_event_nmi_notifier);
 
 	return 0;
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index ce27c54..0a360d1 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1465,7 +1465,7 @@ int __init init_hw_perf_events(void)
 	pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
 	pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
 
-	perf_pmu_register(&pmu);
+	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	perf_cpu_notifier(x86_pmu_notifier);
 
 	return 0;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 30e50e2..21206d2 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -588,6 +588,9 @@ struct perf_event;
 struct pmu {
 	struct list_head		entry;
 
+	char				*name;
+	int				type;
+
 	int * __percpu			pmu_disable_count;
 	struct perf_cpu_context * __percpu pmu_cpu_context;
 	int				task_ctx_nr;
@@ -916,7 +919,7 @@ struct perf_output_handle {
 
 #ifdef CONFIG_PERF_EVENTS
 
-extern int perf_pmu_register(struct pmu *pmu);
+extern int perf_pmu_register(struct pmu *pmu, char *name, int type);
 extern void perf_pmu_unregister(struct pmu *pmu);
 
 extern int perf_num_counters(void);
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index e532582..086adf2 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -641,7 +641,7 @@ int __init init_hw_breakpoint(void)
 
 	constraints_initialized = 1;
 
-	perf_pmu_register(&perf_breakpoint);
+	perf_pmu_register(&perf_breakpoint, "breakpoint", PERF_TYPE_BREAKPOINT);
 
 	return register_die_notifier(&hw_breakpoint_exceptions_nb);
 
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a3d568f..8f09bc8 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
+#include <linux/idr.h>
 #include <linux/file.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -4961,7 +4962,7 @@ static struct pmu perf_tracepoint = {
 
 static inline void perf_tp_register(void)
 {
-	perf_pmu_register(&perf_tracepoint);
+	perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
 }
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -5305,8 +5306,9 @@ static void free_pmu_context(struct pmu *pmu)
 out:
 	mutex_unlock(&pmus_lock);
 }
+static struct idr pmu_idr;
 
-int perf_pmu_register(struct pmu *pmu)
+int perf_pmu_register(struct pmu *pmu, char *name, int type)
 {
 	int cpu, ret;
 
@@ -5316,13 +5318,32 @@ int perf_pmu_register(struct pmu *pmu)
 	if (!pmu->pmu_disable_count)
 		goto unlock;
 
+	pmu->type = -1;
+	if (!name)
+		goto skip_type;
+	pmu->name = name;
+
+	if (type < 0) {
+		int err = idr_pre_get(&pmu_idr, GFP_KERNEL);
+		if (!err)
+			goto free_pdc;
+
+		err = idr_get_new_above(&pmu_idr, pmu, PERF_TYPE_MAX, &type);
+		if (err) {
+			ret = err;
+			goto free_pdc;
+		}
+	}
+	pmu->type = type;
+
+skip_type:
 	pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
 	if (pmu->pmu_cpu_context)
 		goto got_cpu_context;
 
 	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
 	if (!pmu->pmu_cpu_context)
-		goto free_pdc;
+		goto free_ird;
 
 	for_each_possible_cpu(cpu) {
 		struct perf_cpu_context *cpuctx;
@@ -5366,6 +5387,10 @@ unlock:
 
 	return ret;
 
+free_idr:
+	if (pmu->type >= PERF_TYPE_MAX)
+		idr_remove(&pmu_idr, pmu->type);
+
 free_pdc:
 	free_percpu(pmu->pmu_disable_count);
 	goto unlock;
@@ -5385,6 +5410,8 @@ void perf_pmu_unregister(struct pmu *pmu)
 	synchronize_rcu();
 
 	free_percpu(pmu->pmu_disable_count);
+	if (pmu->type >= PERF_TYPE_MAX)
+		idr_remove(&pmu_idr, pmu->type);
 	free_pmu_context(pmu);
 }
 
@@ -5394,6 +5421,13 @@ struct pmu *perf_init_event(struct perf_event *event)
 	int idx;
 
 	idx = srcu_read_lock(&pmus_srcu);
+
+	rcu_read_lock();
+	pmu = idr_find(&pmu_idr, event->attr.type);
+	rcu_read_unlock();
+	if (pmu)
+		goto unlock;
+
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		int ret = pmu->event_init(event);
 		if (!ret)
@@ -6555,11 +6589,13 @@ void __init perf_event_init(void)
 {
 	int ret;
 
+	idr_init(&pmu_idr);
+
 	perf_event_init_all_cpus();
 	init_srcu_struct(&pmus_srcu);
-	perf_pmu_register(&perf_swevent);
-	perf_pmu_register(&perf_cpu_clock);
-	perf_pmu_register(&perf_task_clock);
+	perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);
+	perf_pmu_register(&perf_cpu_clock, NULL, -1);
+	perf_pmu_register(&perf_task_clock, NULL, -1);
 	perf_tp_register();
 	perf_cpu_notifier(perf_cpu_notify);
 	register_reboot_notifier(&perf_reboot_notifier);

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [tip:perf/core] perf: Sysfs enumeration
  2010-11-17 22:17 ` [RFC][PATCH 7/8] perf: Sysfs enumeration Peter Zijlstra
@ 2010-12-16 12:33   ` tip-bot for Peter Zijlstra
  0 siblings, 0 replies; 22+ messages in thread
From: tip-bot for Peter Zijlstra @ 2010-12-16 12:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, kay.sievers, a.p.zijlstra, gregkh, tglx, mingo

Commit-ID:  abe43400579d5de0078c2d3a760e6598e183f871
Gitweb:     http://git.kernel.org/tip/abe43400579d5de0078c2d3a760e6598e183f871
Author:     Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Wed, 17 Nov 2010 23:17:37 +0100
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Thu, 16 Dec 2010 11:36:43 +0100

perf: Sysfs enumeration

Simple sysfs emumeration of the PMUs.

Use a "event_source" bus, and add PMU devices using their name.

Each PMU device has a type attribute which contrains the value needed
for perf_event_attr::type to identify this PMU.

This is the minimal stub needed to start using this interface,
we'll consider extending the sysfs usage later.

Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Greg KH <gregkh@suse.de>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20101117222056.316982569@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 include/linux/perf_event.h |    1 +
 kernel/perf_event.c        |   95 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 21206d2..dda5b0a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -588,6 +588,7 @@ struct perf_event;
 struct pmu {
 	struct list_head		entry;
 
+	struct device			*dev;
 	char				*name;
 	int				type;
 
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 8f09bc8..11847bf 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/reboot.h>
 #include <linux/vmstat.h>
+#include <linux/device.h>
 #include <linux/vmalloc.h>
 #include <linux/hardirq.h>
 #include <linux/rculist.h>
@@ -5308,6 +5309,58 @@ out:
 }
 static struct idr pmu_idr;
 
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *page)
+{
+	struct pmu *pmu = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
+}
+
+static struct device_attribute pmu_dev_attrs[] = {
+       __ATTR_RO(type),
+       __ATTR_NULL,
+};
+
+static int pmu_bus_running;
+static struct bus_type pmu_bus = {
+	.name		= "event_source",
+	.dev_attrs	= pmu_dev_attrs,
+};
+
+static void pmu_dev_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+static int pmu_dev_alloc(struct pmu *pmu)
+{
+	int ret = -ENOMEM;
+
+	pmu->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+	if (!pmu->dev)
+		goto out;
+
+	device_initialize(pmu->dev);
+	ret = dev_set_name(pmu->dev, "%s", pmu->name);
+	if (ret)
+		goto free_dev;
+
+	dev_set_drvdata(pmu->dev, pmu);
+	pmu->dev->bus = &pmu_bus;
+	pmu->dev->release = pmu_dev_release;
+	ret = device_add(pmu->dev);
+	if (ret)
+		goto free_dev;
+
+out:
+	return ret;
+
+free_dev:
+	put_device(pmu->dev);
+	goto out;
+}
+
 int perf_pmu_register(struct pmu *pmu, char *name, int type)
 {
 	int cpu, ret;
@@ -5336,6 +5389,12 @@ int perf_pmu_register(struct pmu *pmu, char *name, int type)
 	}
 	pmu->type = type;
 
+	if (pmu_bus_running) {
+		ret = pmu_dev_alloc(pmu);
+		if (ret)
+			goto free_idr;
+	}
+
 skip_type:
 	pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
 	if (pmu->pmu_cpu_context)
@@ -5343,7 +5402,7 @@ skip_type:
 
 	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
 	if (!pmu->pmu_cpu_context)
-		goto free_ird;
+		goto free_dev;
 
 	for_each_possible_cpu(cpu) {
 		struct perf_cpu_context *cpuctx;
@@ -5387,6 +5446,10 @@ unlock:
 
 	return ret;
 
+free_dev:
+	device_del(pmu->dev);
+	put_device(pmu->dev);
+
 free_idr:
 	if (pmu->type >= PERF_TYPE_MAX)
 		idr_remove(&pmu_idr, pmu->type);
@@ -5412,6 +5475,8 @@ void perf_pmu_unregister(struct pmu *pmu)
 	free_percpu(pmu->pmu_disable_count);
 	if (pmu->type >= PERF_TYPE_MAX)
 		idr_remove(&pmu_idr, pmu->type);
+	device_del(pmu->dev);
+	put_device(pmu->dev);
 	free_pmu_context(pmu);
 }
 
@@ -6603,3 +6668,31 @@ void __init perf_event_init(void)
 	ret = init_hw_breakpoint();
 	WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
 }
+
+static int __init perf_event_sysfs_init(void)
+{
+	struct pmu *pmu;
+	int ret;
+
+	mutex_lock(&pmus_lock);
+
+	ret = bus_register(&pmu_bus);
+	if (ret)
+		goto unlock;
+
+	list_for_each_entry(pmu, &pmus, entry) {
+		if (!pmu->name || pmu->type < 0)
+			continue;
+
+		ret = pmu_dev_alloc(pmu);
+		WARN(ret, "Failed to register pmu: %s, reason %d\n", pmu->name, ret);
+	}
+	pmu_bus_running = 1;
+	ret = 0;
+
+unlock:
+	mutex_unlock(&pmus_lock);
+
+	return ret;
+}
+device_initcall(perf_event_sysfs_init);

^ permalink raw reply related	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2010-12-16 12:33 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-17 22:17 [RFC][PATCH 0/8] perf sysfs bits Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 1/8] perf, x86: Fixup Kconfig deps Peter Zijlstra
2010-11-26 15:01   ` [tip:perf/core] " tip-bot for Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 2/8] perf, arch: Use early_initcall() for all arch pmu implementations Peter Zijlstra
2010-11-25 10:25   ` Peter Zijlstra
2010-11-25 14:47     ` Peter Zijlstra
2010-11-25 16:22       ` Will Deacon
2010-11-25 16:34         ` Peter Zijlstra
2010-11-25 17:55     ` Peter Zijlstra
2010-11-26  7:13       ` Paul Mundt
2010-11-26  9:41       ` Will Deacon
2010-11-26 15:05       ` [tip:perf/core] perf, arch: Cleanup perf-pmu init vs lockup-detector tip-bot for Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 3/8] perf: Move perf_event_init() into main.c Peter Zijlstra
2010-12-16 12:32   ` [tip:perf/core] " tip-bot for Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 4/8] perf: Use early_initcall() for tracepoint and breakpoint init Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 5/8] init: Initialized IRD earlier Peter Zijlstra
2010-12-16 12:32   ` [tip:perf/core] init: Initialized IDR earlier tip-bot for Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 6/8] perf: Dynamic pmu types Peter Zijlstra
2010-12-16 12:32   ` [tip:perf/core] " tip-bot for Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 7/8] perf: Sysfs enumeration Peter Zijlstra
2010-12-16 12:33   ` [tip:perf/core] " tip-bot for Peter Zijlstra
2010-11-17 22:17 ` [RFC][PATCH 8/8] perf: Sysfs events Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).