git: ce9aff829e02 - main - hwpmc_amd: fix amd_get_msr() MSR offset for newer counter bases
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 12 Mar 2026 15:29:09 UTC
The branch main has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=ce9aff829e02c9a21c04eae77a45f2193d1ed5a1
commit ce9aff829e02c9a21c04eae77a45f2193d1ed5a1
Author: Paulo Fragoso <paulo@nlink.com.br>
AuthorDate: 2026-03-12 15:21:33 +0000
Commit: Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2026-03-12 15:29:04 +0000
hwpmc_amd: fix amd_get_msr() MSR offset for newer counter bases
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.
Fix by promoting amd_core_npmcs, amd_l3_npmcs, and amd_df_npmcs to
static module-level variables and computing the correct flat RDPMC
index per AMD BKDG 24594 page 440:
ECX 0-5: Core counters 0-5
ECX 6-9: DF counters 0-3
ECX 10-15: L3 Cache counters 0-5
ECX 16-27: DF counters 4-15
ECX > 27: Reserved, returns EINVAL
Reviewed by: Ali Mashtizadeh <ali@mashtizadeh.com>, mhorne
Sponsored by: NLINK (https://nlink.com.br), Recife, Brazil
Fixes: 37bba2ad92d8 ("hwpmc_amd: Add support for additional counters")
Differential Revision: https://reviews.freebsd.org/D55607
---
sys/dev/hwpmc/hwpmc_amd.c | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index cf44f9362a72..c27d93995d59 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -60,8 +60,8 @@ struct amd_descr {
};
static int amd_npmcs;
+static int amd_core_npmcs, amd_l3_npmcs, amd_df_npmcs;
static struct amd_descr amd_pmcdesc[AMD_NPMCS_MAX];
-
struct amd_event_code_map {
enum pmc_event pe_ev; /* enum value */
uint16_t pe_code; /* encoded event mask */
@@ -664,10 +664,41 @@ amd_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
static int
amd_get_msr(int ri, uint32_t *msr)
{
+ int df_idx;
+
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;
+ /*
+ * Map counter row index to RDPMC ECX value.
+ *
+ * AMD BKDG 24594 rev 3.37, page 440,
+ * "RDPMC Read Performance-Monitoring Counter":
+ * ECX 0-5: Core counters 0-5
+ * ECX 6-9: DF/Northbridge counters 0-3
+ * ECX 10-15: L3 Cache counters 0-5
+ * ECX 16-27: DF/Northbridge counters 4-15
+ *
+ * AMD PPR 57930-A0 section 2.1.9,
+ * "Register Sharing" for DF counter details.
+ */
+ if (ri < amd_core_npmcs) {
+ /* ECX 0-5: Core counters */
+ *msr = ri;
+ } else if (ri < amd_core_npmcs + amd_l3_npmcs) {
+ /* ECX 10-15: L3 Cache counters */
+ *msr = 10 + (ri - amd_core_npmcs);
+ } else {
+ /* ECX 6-9: DF counters 0-3
+ * ECX 16-27: DF counters 4-15 */
+ df_idx = ri - amd_core_npmcs - amd_l3_npmcs;
+ if (df_idx < 4)
+ *msr = 6 + df_idx;
+ else if (df_idx < 16)
+ *msr = 16 + (df_idx - 4);
+ else
+ return (EINVAL);
+ }
return (0);
}
@@ -767,7 +798,6 @@ pmc_amd_initialize(void)
enum pmc_cputype cputype;
int error, i, ncpus, nclasses;
int family, model, stepping;
- int amd_core_npmcs, amd_l3_npmcs, amd_df_npmcs;
struct amd_descr *d;
/*