aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-11-04 18:33:01 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2010-11-12 08:51:55 -0500
commit3c502e7a0255d82621ff25d60cc816624830497e (patch)
tree1f30638f22ef9ed748fac1f73cb18169efe49ae7
parent6c0aca288e726405b01dacb12cac556454d34b2a (diff)
perf,hw_breakpoint: Initialize hardware api earlier
When using early debugging, the kernel does not initialize the hw_breakpoint API early enough and causes the late initialization of the kernel debugger to fail. The boot arguments are: earlyprintk=vga ekgdboc=kbd kgdbwait Then simply type "go" at the kdb prompt and boot. The kernel will later emit the message: kgdb: Could not allocate hwbreakpoints And at that point the kernel debugger will cease to work correctly. The solution is to initialize the hw_breakpoint at the same time that all the other perf call backs are initialized instead of using a core_initcall() initialization which happens well after the kernel debugger can make use of hardware breakpoints. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> CC: Frederic Weisbecker <fweisbec@gmail.com> CC: Ingo Molnar <mingo@elte.hu> CC: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <4CD3396D.1090308@windriver.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
-rw-r--r--include/linux/hw_breakpoint.h4
-rw-r--r--kernel/hw_breakpoint.c3
-rw-r--r--kernel/perf_event.c6
3 files changed, 11 insertions, 2 deletions
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index a2d6ea49ec56..d1e55fed2c7d 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -33,6 +33,8 @@ enum bp_type_idx {
33 33
34#ifdef CONFIG_HAVE_HW_BREAKPOINT 34#ifdef CONFIG_HAVE_HW_BREAKPOINT
35 35
36extern int __init init_hw_breakpoint(void);
37
36static inline void hw_breakpoint_init(struct perf_event_attr *attr) 38static inline void hw_breakpoint_init(struct perf_event_attr *attr)
37{ 39{
38 memset(attr, 0, sizeof(*attr)); 40 memset(attr, 0, sizeof(*attr));
@@ -108,6 +110,8 @@ static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
108 110
109#else /* !CONFIG_HAVE_HW_BREAKPOINT */ 111#else /* !CONFIG_HAVE_HW_BREAKPOINT */
110 112
113static inline int __init init_hw_breakpoint(void) { return 0; }
114
111static inline struct perf_event * 115static inline struct perf_event *
112register_user_hw_breakpoint(struct perf_event_attr *attr, 116register_user_hw_breakpoint(struct perf_event_attr *attr,
113 perf_overflow_handler_t triggered, 117 perf_overflow_handler_t triggered,
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index 2c9120f0afca..e5325825aeb6 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -620,7 +620,7 @@ static struct pmu perf_breakpoint = {
620 .read = hw_breakpoint_pmu_read, 620 .read = hw_breakpoint_pmu_read,
621}; 621};
622 622
623static int __init init_hw_breakpoint(void) 623int __init init_hw_breakpoint(void)
624{ 624{
625 unsigned int **task_bp_pinned; 625 unsigned int **task_bp_pinned;
626 int cpu, err_cpu; 626 int cpu, err_cpu;
@@ -655,6 +655,5 @@ static int __init init_hw_breakpoint(void)
655 655
656 return -ENOMEM; 656 return -ENOMEM;
657} 657}
658core_initcall(init_hw_breakpoint);
659 658
660 659
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 517d827f4982..05b7d8c72c6c 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -31,6 +31,7 @@
31#include <linux/kernel_stat.h> 31#include <linux/kernel_stat.h>
32#include <linux/perf_event.h> 32#include <linux/perf_event.h>
33#include <linux/ftrace_event.h> 33#include <linux/ftrace_event.h>
34#include <linux/hw_breakpoint.h>
34 35
35#include <asm/irq_regs.h> 36#include <asm/irq_regs.h>
36 37
@@ -6295,6 +6296,8 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
6295 6296
6296void __init perf_event_init(void) 6297void __init perf_event_init(void)
6297{ 6298{
6299 int ret;
6300
6298 perf_event_init_all_cpus(); 6301 perf_event_init_all_cpus();
6299 init_srcu_struct(&pmus_srcu); 6302 init_srcu_struct(&pmus_srcu);
6300 perf_pmu_register(&perf_swevent); 6303 perf_pmu_register(&perf_swevent);
@@ -6302,4 +6305,7 @@ void __init perf_event_init(void)
6302 perf_pmu_register(&perf_task_clock); 6305 perf_pmu_register(&perf_task_clock);
6303 perf_tp_register(); 6306 perf_tp_register();
6304 perf_cpu_notifier(perf_cpu_notify); 6307 perf_cpu_notifier(perf_cpu_notify);
6308
6309 ret = init_hw_breakpoint();
6310 WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
6305} 6311}