diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event_p4.c')
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 26 | 
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index c2520e178d3..ead584fb6a7 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -468,7 +468,7 @@ static struct p4_event_bind p4_event_bind_map[] = {  		.opcode		= P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),  		.escr_msr	= { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },  		.escr_emask	= -		P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS), +			P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),  		.cntr		= { {12, 13, 16}, {14, 15, 17} },  	},  	[P4_EVENT_X87_ASSIST] = { @@ -912,8 +912,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)  	int idx, handled = 0;  	u64 val; -	data.addr = 0; -	data.raw = NULL; +	perf_sample_data_init(&data, 0);  	cpuc = &__get_cpu_var(cpu_hw_events); @@ -947,14 +946,23 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)  		if (!x86_perf_event_set_period(event))  			continue;  		if (perf_event_overflow(event, 1, &data, regs)) -			p4_pmu_disable_event(event); +			x86_pmu_stop(event, 0);  	} -	if (handled) { -		/* p4 quirk: unmask it again */ -		apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); +	if (handled)  		inc_irq_stat(apic_perf_irqs); -	} + +	/* +	 * When dealing with the unmasking of the LVTPC on P4 perf hw, it has +	 * been observed that the OVF bit flag has to be cleared first _before_ +	 * the LVTPC can be unmasked. +	 * +	 * The reason is the NMI line will continue to be asserted while the OVF +	 * bit is set.  This causes a second NMI to generate if the LVTPC is +	 * unmasked before the OVF bit is cleared, leading to unknown NMI +	 * messages. +	 */ +	apic_write(APIC_LVTPC, APIC_DM_NMI);  	return handled;  } @@ -1188,7 +1196,7 @@ static __init int p4_pmu_init(void)  {  	unsigned int low, high; -	/* If we get stripped -- indexig fails */ +	/* If we get stripped -- indexing fails */  	BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC);  	rdmsr(MSR_IA32_MISC_ENABLE, low, high);  |