[PATCH 1/2] hwpmc_amd: fix amd_get_msr() MSR offset for newer counter, bases
Paulo Fragoso <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.hackers |
|---|---|
| Message-ID | <[email protected]> |
The previous code subtracted AMD_PMC_PERFCTR_0 (0xC0010004) from all
perfctr MSR addresses to compute a relative offset. This is incorrect
for counters using AMD_PMC_CORE_BASE (0xC0010200), AMD_PMC_L3_BASE
(0xC0010230), and AMD_PMC_DF_BASE (0xC0010240), producing wrong offsets.
For example, core counter 4 (pm_perfctr = 0xC0010209) would produce:
0xC0010209 - 0xC0010004 = 517 (wrong)
instead of:
(0xC0010209 - 0xC0010200) / 2 = 4 (correct)
Fix by computing the MSR offset relative to the correct base address
for each counter sub-class using a switch on pm_subclass field added
by the Netflix hwpmc commit (37bba2ad92d8).
The CORE case handles both legacy processors (using AMD_PMC_PERFCTR_0)
and newer processors with AMDID2_PCXC feature bit (using AMD_PMC_CORE_BASE)
as documented in AMD PPR 57930-A0 page 220:
MSRC001_0200 [Performance Event Select 0] (Core::X86::Msr::PERF_CTL0)
Verified on: AMD Ryzen 5600X (Family 19h, Zen 3), FreeBSD 16.0-CURRENT
- 6 core counters (K8-0..K8-5) ENABLED
- 6 L3 counters (K8-L3-0..K8-L3-5) ENABLED
- 4 DF counters (K8-DF-0..K8-DF-3) ENABLED
Total: 16 K8 PMCs correctly registered
Sponsored by: NLINK (https://nlink.com.br), Recife, Brazil
---
sys/dev/hwpmc/hwpmc_amd.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index 801b75b39595..b7dbbca18da2 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -655,7 +655,24 @@ amd_get_msr(int ri, uint32_t *msr)
KASSERT(ri >= 0 && ri < amd_npmcs,
("[amd,%d] ri %d out of range", __LINE__, ri));
- *msr = amd_pmcdesc[ri].pm_perfctr - AMD_PMC_PERFCTR_0;
+ switch (amd_pmcdesc[ri].pm_subclass) {
+ case PMC_AMD_SUB_CLASS_CORE:
+ if (amd_pmcdesc[ri].pm_perfctr >= AMD_PMC_CORE_BASE)
+ *msr = (amd_pmcdesc[ri].pm_perfctr -
+ AMD_PMC_CORE_BASE) / 2;
+ else
+ *msr = amd_pmcdesc[ri].pm_perfctr -
+ AMD_PMC_PERFCTR_0;
+ break;
+ case PMC_AMD_SUB_CLASS_L3_CACHE:
+ *msr = (amd_pmcdesc[ri].pm_perfctr - AMD_PMC_L3_BASE) / 2;
+ break;
+ case PMC_AMD_SUB_CLASS_DATA_FABRIC:
+ *msr = (amd_pmcdesc[ri].pm_perfctr - AMD_PMC_DF_BASE) / 2;
+ break;
+ default:
+ return (EINVAL);
+ }
return (0);
}
--
2.53.0