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>
This commit is contained in:
parent
5ef428c4b5
commit
004417a6d4
|
@ -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 */
|
||||
|
|
|
@ -112,8 +112,6 @@ init_IRQ(void)
|
|||
wrent(entInt, 0);
|
||||
|
||||
alpha_mv.init_irq();
|
||||
|
||||
init_hw_perf_events();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)... */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -270,8 +270,6 @@ int __init nmi_init(void)
|
|||
atomic_set(&nmi_active, -1);
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
init_hw_perf_events();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue