diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event.c')
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 20 | 
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index ed6310183ef..6d75b9145b1 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -381,6 +381,20 @@ static void release_pmc_hardware(void) {}  #endif +static bool check_hw_exists(void) +{ +	u64 val, val_new = 0; +	int ret = 0; + +	val = 0xabcdUL; +	ret |= checking_wrmsrl(x86_pmu.perfctr, val); +	ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new); +	if (ret || val != val_new) +		return false; + +	return true; +} +  static void reserve_ds_buffers(void);  static void release_ds_buffers(void); @@ -1372,6 +1386,12 @@ void __init init_hw_perf_events(void)  	pmu_check_apic(); +	/* sanity check that the hardware exists or is emulated */ +	if (!check_hw_exists()) { +		pr_cont("Broken PMU hardware detected, software events only.\n"); +		return; +	} +  	pr_cont("%s PMU driver.\n", x86_pmu.name);  	if (x86_pmu.quirks)  |