| From 26e52558ead4b39c0e0fe7bf08f82f5a9777a412 Mon Sep 17 00:00:00 2001 |
| From: Kim Phillips <kim.phillips@amd.com> |
| Date: Tue, 8 Sep 2020 16:47:35 -0500 |
| Subject: perf/x86/amd: Fix sampling Large Increment per Cycle events |
| |
| From: Kim Phillips <kim.phillips@amd.com> |
| |
| commit 26e52558ead4b39c0e0fe7bf08f82f5a9777a412 upstream. |
| |
| Commit 5738891229a2 ("perf/x86/amd: Add support for Large Increment |
| per Cycle Events") mistakenly zeroes the upper 16 bits of the count |
| in set_period(). That's fine for counting with perf stat, but not |
| sampling with perf record when only Large Increment events are being |
| sampled. To enable sampling, we sign extend the upper 16 bits of the |
| merged counter pair as described in the Family 17h PPRs: |
| |
| "Software wanting to preload a value to a merged counter pair writes the |
| high-order 16-bit value to the low-order 16 bits of the odd counter and |
| then writes the low-order 48-bit value to the even counter. Reading the |
| even counter of the merged counter pair returns the full 64-bit value." |
| |
| Fixes: 5738891229a2 ("perf/x86/amd: Add support for Large Increment per Cycle Events") |
| Signed-off-by: Kim Phillips <kim.phillips@amd.com> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Cc: stable@vger.kernel.org |
| Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537 |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/events/core.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/events/core.c |
| +++ b/arch/x86/events/core.c |
| @@ -1286,11 +1286,11 @@ int x86_perf_event_set_period(struct per |
| wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask); |
| |
| /* |
| - * Clear the Merge event counter's upper 16 bits since |
| + * Sign extend the Merge event counter's upper 16 bits since |
| * we currently declare a 48-bit counter width |
| */ |
| if (is_counter_pair(hwc)) |
| - wrmsrl(x86_pmu_event_addr(idx + 1), 0); |
| + wrmsrl(x86_pmu_event_addr(idx + 1), 0xffff); |
| |
| /* |
| * Due to erratum on certan cpu we need |