diff options
| -rw-r--r-- | arch/x86/include/asm/perf_event_p4.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 11 |
2 files changed, 9 insertions, 3 deletions
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index e2f6a99f14ab..cc29086e30cd 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #define ARCH_P4_CNTRVAL_BITS (40) | 23 | #define ARCH_P4_CNTRVAL_BITS (40) |
| 24 | #define ARCH_P4_CNTRVAL_MASK ((1ULL << ARCH_P4_CNTRVAL_BITS) - 1) | 24 | #define ARCH_P4_CNTRVAL_MASK ((1ULL << ARCH_P4_CNTRVAL_BITS) - 1) |
| 25 | #define ARCH_P4_UNFLAGGED_BIT ((1ULL) << (ARCH_P4_CNTRVAL_BITS - 1)) | ||
| 25 | 26 | ||
| 26 | #define P4_ESCR_EVENT_MASK 0x7e000000U | 27 | #define P4_ESCR_EVENT_MASK 0x7e000000U |
| 27 | #define P4_ESCR_EVENT_SHIFT 25 | 28 | #define P4_ESCR_EVENT_SHIFT 25 |
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index f7a0993c1e7c..ff751a9f182b 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c | |||
| @@ -770,9 +770,14 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) | |||
| 770 | return 1; | 770 | return 1; |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | /* it might be unflagged overflow */ | 773 | /* |
| 774 | rdmsrl(hwc->event_base + hwc->idx, v); | 774 | * In some circumstances the overflow might issue an NMI but did |
| 775 | if (!(v & ARCH_P4_CNTRVAL_MASK)) | 775 | * not set P4_CCCR_OVF bit. Because a counter holds a negative value |
| 776 | * we simply check for high bit being set, if it's cleared it means | ||
| 777 | * the counter has reached zero value and continued counting before | ||
| 778 | * real NMI signal was received: | ||
| 779 | */ | ||
| 780 | if (!(v & ARCH_P4_UNFLAGGED_BIT)) | ||
| 776 | return 1; | 781 | return 1; |
| 777 | 782 | ||
| 778 | return 0; | 783 | return 0; |
