From df0339f56243f35cd5cfab44ad2ec03957dc0260 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 17 May 2010 16:13:04 +0800 Subject: [PATCH] --- yaml --- r: 199088 b: refs/heads/master c: 0db1a7bc00216a981d0b7056627ad8682f4f0636 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/cpu/perf_event_p4.c | 32 +++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/[refs] b/[refs] index f51ee6dce22d..47265378a559 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 32ec6acfdcc066313261d0fbe6a966cb1804a7cd +refs/heads/master: 0db1a7bc00216a981d0b7056627ad8682f4f0636 diff --git a/trunk/arch/x86/kernel/cpu/perf_event_p4.c b/trunk/arch/x86/kernel/cpu/perf_event_p4.c index 424fc8de68e4..02f072830237 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_p4.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_p4.c @@ -465,15 +465,21 @@ static int p4_hw_config(struct perf_event *event) return rc; } -static inline void p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) +static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) { - unsigned long dummy; + int overflow = 0; + u32 low, high; - rdmsrl(hwc->config_base + hwc->idx, dummy); - if (dummy & P4_CCCR_OVF) { + rdmsr(hwc->config_base + hwc->idx, low, high); + + /* we need to check high bit for unflagged overflows */ + if ((low & P4_CCCR_OVF) || (high & (1 << 31))) { + overflow = 1; (void)checking_wrmsrl(hwc->config_base + hwc->idx, - ((u64)dummy) & ~P4_CCCR_OVF); + ((u64)low) & ~P4_CCCR_OVF); } + + return overflow; } static inline void p4_pmu_disable_event(struct perf_event *event) @@ -584,21 +590,15 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) WARN_ON_ONCE(hwc->idx != idx); - /* - * FIXME: Redundant call, actually not needed - * but just to check if we're screwed - */ - p4_pmu_clear_cccr_ovf(hwc); + /* it might be unflagged overflow */ + handled = p4_pmu_clear_cccr_ovf(hwc); val = x86_perf_event_update(event); - if (val & (1ULL << (x86_pmu.cntval_bits - 1))) + if (!handled && (val & (1ULL << (x86_pmu.cntval_bits - 1)))) continue; - /* - * event overflow - */ - handled = 1; - data.period = event->hw.last_period; + /* event overflow for sure */ + data.period = event->hw.last_period; if (!x86_perf_event_set_period(event)) continue;