[PATCH 2/2] hwpmc_amd: fix DF counter MSR sharing in amd_pcpu_init()
Paulo Fragoso <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.hackers |
|---|---|
| Message-ID | <[email protected]> |
AMD Data Fabric (DF) performance counter MSRs are shared across all
cores in a package. From AMD PPR 57930-A0 section 2.1.9 [Register
Sharing]:
'The DF Performance Monitors are shared by all cores/threads in
the socket. Software must coordinate writing to shared registers
with other threads in the same sharing hierarchy level.'
Previously, amd_pcpu_init() marked DF counters as PMC_PHW_FLAG_IS_ENABLED
on all CPUs. This caused KASSERT failures in amd_start_pmc() and
amd_stop_pmc() when multiple CPUs attempted to start/stop the same
shared MSRs simultaneously, as AMD_PMC_IS_STOPPED() reads the physical
MSR state which is visible to all cores.
Fix by marking DF counters as enabled only on the package master CPU
(cpu_top->cg_first, the lowest CPU ID in the package). The MI layer
returns EPERM for allocation attempts on non-master CPUs, preventing
concurrent MSR access. DF counters remain functional via CPU 0 using
'pmcstat -c 0 -s <df_event>'.
Tested on: AMD Ryzen 5600X (Family 19h, Zen 3), FreeBSD 16.0-CURRENT
- DF counters ENABLED on CPU 0 only
- DF counters DISABLED on CPUs 1-11
- dram_channel_data_controller_0 returns valid counts on CPU 0
Sponsored by: NLINK (https://nlink.com.br), Recife, Brazil
---
sys/dev/hwpmc/hwpmc_amd.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index b7dbbca18da2..0013228da82d 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -705,8 +705,23 @@ amd_pcpu_init(struct pmc_mdep *md, int cpu)
KASSERT(pc != NULL, ("[amd,%d] NULL per-cpu pointer", __LINE__));
for (n = 0, phw = pac->pc_amdpmcs; n < amd_npmcs; n++, phw++) {
- phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
- PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n);
+ /*
+ * DF MSRs are shared across all cores in the package.
+ * See AMD PPR section 2.1.9 [Register Sharing].
+ * Only mark DF counters as enabled on the package
+ * master CPU (lowest CPU ID in the package, cg_first
+ * of cpu_top) to prevent multiple CPUs from writing
+ * the shared MSRs simultaneously.
+ */
+ if (amd_pmcdesc[n].pm_subclass ==
+ PMC_AMD_SUB_CLASS_DATA_FABRIC &&
+ cpu != cpu_top->cg_first) {
+ phw->phw_state = 0;
+ } else {
+ phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
+ PMC_PHW_CPU_TO_STATE(cpu) |
+ PMC_PHW_INDEX_TO_STATE(n);
+ }
phw->phw_pmc = NULL;
pc->pc_hwpmcs[n + first_ri] = phw;
}
--
2.53.0