perf/x86/amd/uncore: Use rdmsr if rdpmc is unavailable
authorSandipan Das <sandipan.das@amd.com>
Thu, 5 Oct 2023 05:23:13 +0000 (10:53 +0530)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 9 Oct 2023 14:12:24 +0000 (16:12 +0200)
Not all uncore PMUs may support the use of the RDPMC instruction for
reading counters. In such cases, read the count from the corresponding
PERF_CTR register using the RDMSR instruction.

Signed-off-by: Sandipan Das <sandipan.das@amd.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/e9d994e32a3fcb39fa59fcf43ab4260d11aba097.1696425185.git.sandipan.das@amd.com
arch/x86/events/amd/uncore.c

index ff1d09cc07ad33171a0ee7d980a9db07e4e6e03b..2fe62392303409d51b0313a34d9df8e89f97bc99 100644 (file)
@@ -96,7 +96,16 @@ static void amd_uncore_read(struct perf_event *event)
         */
 
        prev = local64_read(&hwc->prev_count);
-       rdpmcl(hwc->event_base_rdpmc, new);
+
+       /*
+        * Some uncore PMUs do not have RDPMC assignments. In such cases,
+        * read counts directly from the corresponding PERF_CTR.
+        */
+       if (hwc->event_base_rdpmc < 0)
+               rdmsrl(hwc->event_base, new);
+       else
+               rdpmcl(hwc->event_base_rdpmc, new);
+
        local64_set(&hwc->prev_count, new);
        delta = (new << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
        delta >>= COUNTER_SHIFT;
@@ -164,6 +173,9 @@ out:
        hwc->event_base_rdpmc = pmu->rdpmc_base + hwc->idx;
        hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
 
+       if (pmu->rdpmc_base < 0)
+               hwc->event_base_rdpmc = -1;
+
        if (flags & PERF_EF_START)
                event->pmu->start(event, PERF_EF_RELOAD);