Skip to content

Commit 004417a

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
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 <[email protected]> Cc: davem <[email protected]> Cc: Michael Cree <[email protected]> Cc: Deng-Cheng Zhu <[email protected]> Acked-by: Paul Mundt <[email protected]> Acked-by: Will Deacon <[email protected]> Signed-off-by: Peter Zijlstra <[email protected]> LKML-Reference: <1290707759.2145.119.camel@laptop> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 5ef428c commit 004417a

File tree

24 files changed

+38
-42
lines changed

24 files changed

+38
-42
lines changed

arch/alpha/include/asm/perf_event.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
#ifndef __ASM_ALPHA_PERF_EVENT_H
22
#define __ASM_ALPHA_PERF_EVENT_H
33

4-
#ifdef CONFIG_PERF_EVENTS
5-
extern void init_hw_perf_events(void);
6-
#else
7-
static inline void init_hw_perf_events(void) { }
8-
#endif
9-
104
#endif /* __ASM_ALPHA_PERF_EVENT_H */

arch/alpha/kernel/irq_alpha.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ init_IRQ(void)
112112
wrent(entInt, 0);
113113

114114
alpha_mv.init_irq();
115-
116-
init_hw_perf_events();
117115
}
118116

119117
/*

arch/alpha/kernel/perf_event.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/kernel.h>
1515
#include <linux/kdebug.h>
1616
#include <linux/mutex.h>
17+
#include <linux/init.h>
1718

1819
#include <asm/hwrpb.h>
1920
#include <asm/atomic.h>
@@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
863864
/*
864865
* Init call to initialise performance events at kernel startup.
865866
*/
866-
void __init init_hw_perf_events(void)
867+
int __init init_hw_perf_events(void)
867868
{
868869
pr_info("Performance events: ");
869870

870871
if (!supported_cpu()) {
871872
pr_cont("No support for your CPU.\n");
872-
return;
873+
return 0;
873874
}
874875

875876
pr_cont("Supported CPU type!\n");
@@ -882,5 +883,7 @@ void __init init_hw_perf_events(void)
882883
alpha_pmu = &ev67_pmu;
883884

884885
perf_pmu_register(&pmu);
885-
}
886886

887+
return 0;
888+
}
889+
early_initcall(init_hw_perf_events);

arch/arm/kernel/perf_event.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3038,7 +3038,7 @@ init_hw_perf_events(void)
30383038

30393039
return 0;
30403040
}
3041-
arch_initcall(init_hw_perf_events);
3041+
early_initcall(init_hw_perf_events);
30423042

30433043
/*
30443044
* Callchain handling code.

arch/mips/kernel/perf_event_mipsxx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,6 @@ init_hw_perf_events(void)
10471047

10481048
return 0;
10491049
}
1050-
arch_initcall(init_hw_perf_events);
1050+
early_initcall(init_hw_perf_events);
10511051

10521052
#endif /* defined(CONFIG_CPU_MIPS32)... */

arch/powerpc/kernel/e500-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,4 @@ static int init_e500_pmu(void)
126126
return register_fsl_emb_pmu(&e500_pmu);
127127
}
128128

129-
arch_initcall(init_e500_pmu);
129+
early_initcall(init_e500_pmu);

arch/powerpc/kernel/mpc7450-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,4 +414,4 @@ static int init_mpc7450_pmu(void)
414414
return register_power_pmu(&mpc7450_pmu);
415415
}
416416

417-
arch_initcall(init_mpc7450_pmu);
417+
early_initcall(init_mpc7450_pmu);

arch/powerpc/kernel/power4-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,4 +613,4 @@ static int init_power4_pmu(void)
613613
return register_power_pmu(&power4_pmu);
614614
}
615615

616-
arch_initcall(init_power4_pmu);
616+
early_initcall(init_power4_pmu);

arch/powerpc/kernel/power5+-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,4 +682,4 @@ static int init_power5p_pmu(void)
682682
return register_power_pmu(&power5p_pmu);
683683
}
684684

685-
arch_initcall(init_power5p_pmu);
685+
early_initcall(init_power5p_pmu);

arch/powerpc/kernel/power5-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,4 +621,4 @@ static int init_power5_pmu(void)
621621
return register_power_pmu(&power5_pmu);
622622
}
623623

624-
arch_initcall(init_power5_pmu);
624+
early_initcall(init_power5_pmu);

arch/powerpc/kernel/power6-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,4 +544,4 @@ static int init_power6_pmu(void)
544544
return register_power_pmu(&power6_pmu);
545545
}
546546

547-
arch_initcall(init_power6_pmu);
547+
early_initcall(init_power6_pmu);

arch/powerpc/kernel/power7-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,4 +369,4 @@ static int init_power7_pmu(void)
369369
return register_power_pmu(&power7_pmu);
370370
}
371371

372-
arch_initcall(init_power7_pmu);
372+
early_initcall(init_power7_pmu);

arch/powerpc/kernel/ppc970-pmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,4 +494,4 @@ static int init_ppc970_pmu(void)
494494
return register_power_pmu(&ppc970_pmu);
495495
}
496496

497-
arch_initcall(init_ppc970_pmu);
497+
early_initcall(init_ppc970_pmu);

arch/sh/kernel/cpu/sh4/perf_event.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,4 @@ static int __init sh7750_pmu_init(void)
250250

251251
return register_sh_pmu(&sh7750_pmu);
252252
}
253-
arch_initcall(sh7750_pmu_init);
253+
early_initcall(sh7750_pmu_init);

arch/sh/kernel/cpu/sh4a/perf_event.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,4 @@ static int __init sh4a_pmu_init(void)
284284

285285
return register_sh_pmu(&sh4a_pmu);
286286
}
287-
arch_initcall(sh4a_pmu_init);
287+
early_initcall(sh4a_pmu_init);

arch/sparc/include/asm/perf_event.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#ifdef CONFIG_PERF_EVENTS
55
#include <asm/ptrace.h>
66

7-
extern void init_hw_perf_events(void);
8-
97
#define perf_arch_fetch_caller_regs(regs, ip) \
108
do { \
119
unsigned long _pstate, _asi, _pil, _i7, _fp; \
@@ -26,8 +24,6 @@ do { \
2624
(regs)->u_regs[UREG_I6] = _fp; \
2725
(regs)->u_regs[UREG_I7] = _i7; \
2826
} while (0)
29-
#else
30-
static inline void init_hw_perf_events(void) { }
3127
#endif
3228

3329
#endif

arch/sparc/kernel/nmi.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,6 @@ int __init nmi_init(void)
270270
atomic_set(&nmi_active, -1);
271271
}
272272
}
273-
if (!err)
274-
init_hw_perf_events();
275273

276274
return err;
277275
}

arch/sparc/kernel/perf_event.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void)
13071307
return false;
13081308
}
13091309

1310-
void __init init_hw_perf_events(void)
1310+
int __init init_hw_perf_events(void)
13111311
{
13121312
pr_info("Performance events: ");
13131313

13141314
if (!supported_pmu()) {
13151315
pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
1316-
return;
1316+
return 0;
13171317
}
13181318

13191319
pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
13201320

13211321
perf_pmu_register(&pmu);
13221322
register_die_notifier(&perf_event_nmi_notifier);
1323+
1324+
return 0;
13231325
}
1326+
early_initcall(init_hw_perf_event);
13241327

13251328
void perf_callchain_kernel(struct perf_callchain_entry *entry,
13261329
struct pt_regs *regs)

arch/x86/include/asm/perf_event.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ union cpuid10_edx {
125125
#define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */
126126

127127
#ifdef CONFIG_PERF_EVENTS
128-
extern void init_hw_perf_events(void);
129128
extern void perf_events_lapic_init(void);
130129

131130
#define PERF_EVENT_INDEX_OFFSET 0
@@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
156155
}
157156

158157
#else
159-
static inline void init_hw_perf_events(void) { }
160158
static inline void perf_events_lapic_init(void) { }
161159
#endif
162160

arch/x86/kernel/cpu/common.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,6 @@ void __init identify_boot_cpu(void)
894894
#else
895895
vgetcpu_set_mode();
896896
#endif
897-
init_hw_perf_events();
898897
}
899898

900899
void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)

arch/x86/kernel/cpu/perf_event.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ static void __init pmu_check_apic(void)
13531353
pr_info("no hardware sampling interrupt available.\n");
13541354
}
13551355

1356-
void __init init_hw_perf_events(void)
1356+
int __init init_hw_perf_events(void)
13571357
{
13581358
struct event_constraint *c;
13591359
int err;
@@ -1368,19 +1368,19 @@ void __init init_hw_perf_events(void)
13681368
err = amd_pmu_init();
13691369
break;
13701370
default:
1371-
return;
1371+
return 0;
13721372
}
13731373
if (err != 0) {
13741374
pr_cont("no PMU driver, software events only.\n");
1375-
return;
1375+
return 0;
13761376
}
13771377

13781378
pmu_check_apic();
13791379

13801380
/* sanity check that the hardware exists or is emulated */
13811381
if (!check_hw_exists()) {
13821382
pr_cont("Broken PMU hardware detected, software events only.\n");
1383-
return;
1383+
return 0;
13841384
}
13851385

13861386
pr_cont("%s PMU driver.\n", x86_pmu.name);
@@ -1431,7 +1431,10 @@ void __init init_hw_perf_events(void)
14311431

14321432
perf_pmu_register(&pmu);
14331433
perf_cpu_notifier(x86_pmu_notifier);
1434+
1435+
return 0;
14341436
}
1437+
early_initcall(init_hw_perf_events);
14351438

14361439
static inline void x86_pmu_read(struct perf_event *event)
14371440
{

include/linux/sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ extern int proc_dowatchdog_thresh(struct ctl_table *table, int write,
316316
size_t *lenp, loff_t *ppos);
317317
extern unsigned int softlockup_panic;
318318
extern int softlockup_thresh;
319+
void lockup_detector_init(void);
319320
#else
320321
static inline void touch_softlockup_watchdog(void)
321322
{
@@ -326,6 +327,9 @@ static inline void touch_softlockup_watchdog_sync(void)
326327
static inline void touch_all_softlockup_watchdogs(void)
327328
{
328329
}
330+
static inline void lockup_detector_init(void)
331+
{
332+
}
329333
#endif
330334

331335
#ifdef CONFIG_DETECT_HUNG_TASK

init/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ static int __init kernel_init(void * unused)
882882
smp_prepare_cpus(setup_max_cpus);
883883

884884
do_pre_smp_initcalls();
885+
lockup_detector_init();
885886

886887
smp_init();
887888
sched_init_smp();

kernel/watchdog.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,20 +547,19 @@ static struct notifier_block __cpuinitdata cpu_nfb = {
547547
.notifier_call = cpu_callback
548548
};
549549

550-
static int __init spawn_watchdog_task(void)
550+
void __init lockup_detector_init(void)
551551
{
552552
void *cpu = (void *)(long)smp_processor_id();
553553
int err;
554554

555555
if (no_watchdog)
556-
return 0;
556+
return;
557557

558558
err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
559559
WARN_ON(notifier_to_errno(err));
560560

561561
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
562562
register_cpu_notifier(&cpu_nfb);
563563

564-
return 0;
564+
return;
565565
}
566-
early_initcall(spawn_watchdog_task);

0 commit comments

Comments
 (0)