Messages in this thread Patch in this message | | | Date | Fri, 19 Nov 2010 00:56:50 +0300 | From | Cyrill Gorcunov <> | Subject | Re: [V2 PATCH 0/6] x86, NMI: give NMI handler a face-lift |
| |
On Thu, Nov 18, 2010 at 02:32:47PM -0500, Don Zickus wrote: ... > On a side note I think I have a fix for the p4 problem but will probably > need Cyril to look at it. Basically in, p4_pmu_clear_cccr_ovf() it is > using the high part of the cccr register to determine if the counter > overflowed, when it probably wants to use the low bits of the cccr > register and high bits of the event_base. >
Thanks a hige Don for pointing to the problem. Here is the patch.
Cyrill --- perf, x86: P4 PMU - Fix unflagged overflows handling
Jason pointed out that kgdb no longer works with new nmi-watchdog. Don found the reason -- P4 PMU reads CCCR register instead of counter itself, it forces NMIs to be eaten by perf subsystem.
Fix it by reading a proper register.
Reported-by: Jason Wessel <jason.wessel@windriver.com> Reported-by: Don Zickus <dzickus@redhat.com> Tested-by: Jason Wessel <jason.wessel@windriver.com> Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> --- arch/x86/kernel/cpu/perf_event_p4.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
Index: linux-2.6.git/arch/x86/kernel/cpu/perf_event_p4.c ===================================================================== --- linux-2.6.git.orig/arch/x86/kernel/cpu/perf_event_p4.c +++ linux-2.6.git/arch/x86/kernel/cpu/perf_event_p4.c @@ -753,19 +753,22 @@ out: static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) { - int overflow = 0; - u32 low, high; + u32 overflow = 0; + u32 low, low_cccr, high; - rdmsr(hwc->config_base + hwc->idx, low, high); + /* an official way for overflow indication */ + rdmsr(hwc->config_base + hwc->idx, low_cccr, high); + overflow |= (low_cccr & P4_CCCR_OVF); + + /* unflagged overflows */ + rdmsr(hwc->event_base + hwc->idx, low, high); + overflow |= high & 0x80000000; - /* we need to check high bit for unflagged overflows */ - if ((low & P4_CCCR_OVF) || !(high & (1 << 31))) { - overflow = 1; + if (overflow) (void)checking_wrmsrl(hwc->config_base + hwc->idx, - ((u64)low) & ~P4_CCCR_OVF); - } + ((u64)low_cccr) & ~P4_CCCR_OVF); - return overflow; + return overflow > 0; } static void p4_pmu_disable_pebs(void)
| |