From nobody Mon Sep 21 22:50:43 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hpdjw1QgTz6sJqW for ; Mon, 21 Sep 2026 22:50:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hpdjw0NDBz3CWD for ; Mon, 21 Sep 2026 22:50:44 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790031044; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Fr8cL5APr9nTqSjJG2WEJN8k7YISbWlEfmV/A3Cz4Cg=; b=CIYdO1xu0QSvHZJ6GKg8llOFTH2JmBunGJMBHrobhCpCDZDLHuY0+xStwmJCstdqGCOGGN fcDTxBOmOw1J5+r+QnxW0tqtVazbh838QC0lrr26POR/NHFmj1Rza0M38LgAJkoe0TQX5N 7AVE9abdBDUXtDkX34i6tpImtvs8MYMMQbhujQd7itYQZBejwZlG2F8qGQo3EUzhL8rGTn eIkoUR8LADGny4Z4ddJlWrQfLd5ITb2bI+5DEbp+H8BolQ+0fS4dcKO/qACvHeUJkpd3CS J/0JqAEEUkXUt0F+R9knFAUzUqLI1Kcem5djO8Vc18bjfc4ouF1SbzNe0rCT6Q== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1790031044; b=mRml655GQBqEZbMua/HNRcvZqHgnD3AAP+bwIOWcv6PV1UriPTcU0FmVisslKHpI/yTVRT SxGVMtWVtEltpM+flbvzcNUxE5WhVmhxFPktP1m4TMaz/UlhZrDDAN+fhFxAgOiIq/Ju3/ hw5AkecmYxBOGutq9inSQEU9Ii8inSPW+UmjbriMODa60hp/Kspds5jwzJee+d8/aZuk0r FAoqIc8tiY6CfhziyaEAHFAu2uNf/+Qjn8nVSU07gk/aYI/Bw/Y1KFLwKurlg9GZkQ7fYA Z6ynJQ+nRa5GwqUtjX6Q7JKjYQRxw7b2xVhcav5oUjJfvcCKZ9gdH+4zqXUSuA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790031044; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Fr8cL5APr9nTqSjJG2WEJN8k7YISbWlEfmV/A3Cz4Cg=; b=jzAfbH8FOOhXDcHuwc/wmb2eCRELwICmN0vF3mCP/TOONYlI5TrQBvFs4PjkdCZoQNifKg U4FpEVheub0MPp+p4p+oZ9b9IjOqXaJe85iwABmowtaPWkJhFkNOXe0j8W0Gc4jgaRbr3T pij/DC5EvIdU3+FDXzs+WNbSbkUk0DFAgAKSoGH6/ZZulpXpSQ5hoBLWb2ubgxYfkJXBx2 g6TA8EFI3rcKht3d4WoWy5zWA1HZVT74PS/4IAxLwSP7MevF55Xj5o31/Q6SKD2zFKoman cSk5LICLEV0DJXEpKLEDQw1+AQxijkShKzzammWnpse8H4i79+HLoGXuDbwwGA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hpdjv6Qx8zh1q for ; Mon, 21 Sep 2026 22:50:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 39cc9 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 21 Sep 2026 22:50:43 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Osvaldo Janeri Filho From: Mitchell Horne Subject: git: 8a0cab240f21 - main - hwpmc/amd: replace static pmcdesc[] and pc_amdpmcs[] with dynamic allocation List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mhorne X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 8a0cab240f2146a000396c411df471df4b75bb9d Auto-Submitted: auto-generated Date: Mon, 21 Sep 2026 22:50:43 +0000 Message-Id: <6ab1b4c3.39cc9.58e143a8@gitrepo.freebsd.org> The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=8a0cab240f2146a000396c411df471df4b75bb9d commit 8a0cab240f2146a000396c411df471df4b75bb9d Author: Osvaldo Janeri Filho AuthorDate: 2026-09-09 15:13:52 +0000 Commit: Mitchell Horne CommitDate: 2026-09-21 22:49:42 +0000 hwpmc/amd: replace static pmcdesc[] and pc_amdpmcs[] with dynamic allocation AMD_NPMCS_MAX = 342 (16 core + 6 L3 + 64 DF + 256 UMC). On a Zen 4 EPYC 9654 with 6 core, 6 L3, 16 DF, and 4 UMC counters, only 32 descriptors are needed; the static arrays over-allocate by ~10x. Replace both amd_pmcdesc[AMD_NPMCS_MAX] and per-CPU pc_amdpmcs[AMD_NPMCS_MAX] with mallocarray() sized to the actual registered PMC count: - amd_pmcdesc: allocated in pmc_amd_initialize() - pc_amdpmcs: allocated per-CPU in amd_pcpu_init(), freed in fini() Normalize amd_l3_npmcs and amd_df_npmcs against the AMDID2_PTSCEL2I and AMDID2_PNXC feature bits before computing npmcs_total, so that allocation, registration, and amd_get_msr() row offsets are all derived from the same values. Previously the ternary in npmcs_total excluded L3/DF from the allocation while the globals retained their defaults, causing amd_get_msr() to miscompute DF row offsets when L3 is absent. amd_umc_npmcs comes from CPUID Fn8000_0022h EBX[23:16] (NumUMCCounters) and is zero when the leaf is absent, so no additional feature flag is needed. See AMD64 APM Vol.3 Appendix E. Fix three error-path memory leaks: amd_hwcheck() failure, goto error, and finalize. Reset amd_npmcs = 0 on the error path. Tested on AMD EPYC 9654 (Zen 4, Family 19h Model 11h, 192 threads). Full PMC test suite (IBS/UMCDF/PMC/L3/DF/TSC): 0 failures. Signed-off-by: Osvaldo Janeri Filho Reviewed by: mhorne MFC after: 1 week Sponsored by: AMD Pull Request: https://github.com/freebsd/freebsd-src/pull/2415 --- sys/dev/hwpmc/hwpmc_amd.c | 43 +++++++++++++++++++++++++++++++++++++++++-- sys/dev/hwpmc/hwpmc_amd.h | 3 ++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index c75bb9d0d14c..232c59aea3bf 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -65,7 +65,7 @@ struct amd_descr { static int amd_npmcs; static int amd_core_npmcs, amd_l3_npmcs, amd_df_npmcs, amd_umc_npmcs; -static struct amd_descr amd_pmcdesc[AMD_NPMCS_MAX]; +static struct amd_descr *amd_pmcdesc; struct amd_event_code_map { enum pmc_event pe_ev; /* enum value */ uint16_t pe_code; /* encoded event mask */ @@ -178,7 +178,7 @@ const int amd_event_codes_size = nitems(amd_event_codes); * Per-processor information */ struct amd_cpu { - struct pmc_hw pc_amdpmcs[AMD_NPMCS_MAX]; + struct pmc_hw *pc_amdpmcs; }; static struct amd_cpu **amd_pcpu; @@ -840,6 +840,8 @@ amd_pcpu_init(struct pmc_mdep *md, int cpu) amd_pcpu[cpu] = pac = malloc(sizeof(struct amd_cpu), M_PMC, M_WAITOK | M_ZERO); + pac->pc_amdpmcs = mallocarray(amd_npmcs, sizeof(*pac->pc_amdpmcs), + M_PMC, M_WAITOK | M_ZERO); /* * Set the content of the hardware descriptors to a known @@ -903,6 +905,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) for (i = 0; i < amd_npmcs; i++) pc->pc_hwpmcs[i + first_ri] = NULL; + free(pac->pc_amdpmcs, M_PMC); free(pac, M_PMC); return (0); } @@ -988,6 +991,7 @@ pmc_amd_initialize(void) enum pmc_cputype cputype; int ncpus, nclasses, i; int family, model, stepping; + int npmcs_total; int error; int pmcs_per_umc; @@ -1046,6 +1050,24 @@ pmc_amd_initialize(void) } } + /* + * Normalize per-class counts against feature bits so that allocation, + * registration, and amd_get_msr() row offsets all use the same values. + * UMC counters have no CPUID feature flag; amd_umc_npmcs is 0 when + * the CPUID leaf is absent. + */ + if ((amd_feature2 & AMDID2_PTSCEL2I) == 0) + amd_l3_npmcs = 0; + if ((amd_feature2 & AMDID2_PNXC) == 0) + amd_df_npmcs = 0; + npmcs_total = amd_core_npmcs + amd_l3_npmcs + amd_df_npmcs + + amd_umc_npmcs; + KASSERT(npmcs_total <= AMD_NPMCS_MAX, + ("%s: npmcs_total %d exceeds AMD_NPMCS_MAX %d", + __func__, npmcs_total, AMD_NPMCS_MAX)); + amd_pmcdesc = mallocarray(npmcs_total, sizeof(*amd_pmcdesc), + M_PMC, M_WAITOK | M_ZERO); + /* Enable the newer core counters */ for (i = 0; i < amd_core_npmcs; i++) { d = &amd_pmcdesc[i]; @@ -1105,6 +1127,9 @@ pmc_amd_initialize(void) amd_npmcs += amd_df_npmcs; } + KASSERT(amd_npmcs == npmcs_total - amd_umc_npmcs, + ("%s: UMC cursor wrong: got %d expected %d", + __func__, amd_npmcs, npmcs_total - amd_umc_npmcs)); for (i = 0; i < amd_umc_npmcs; i++) { d = &amd_pmcdesc[amd_npmcs + i]; snprintf(d->pm_descr.pd_name, PMC_NAME_MAX, @@ -1118,11 +1143,17 @@ pmc_amd_initialize(void) } amd_npmcs += amd_umc_npmcs; + KASSERT(amd_npmcs == npmcs_total, + ("%s: descriptor cursor %d != npmcs_total %d", + __func__, amd_npmcs, npmcs_total)); + /* * Sanity check that the hardware is safe to use. Do not read or write * any of the PMC MSRs until after this check passes. */ if (amd_hwcheck() < 0) { + free(amd_pmcdesc, M_PMC); + amd_pmcdesc = NULL; return (NULL); } @@ -1216,6 +1247,11 @@ pmc_amd_initialize(void) error: free(pmc_mdep, M_PMC); + free(amd_pcpu, M_PMC); + amd_pcpu = NULL; + free(amd_pmcdesc, M_PMC); + amd_pmcdesc = NULL; + amd_npmcs = 0; return (NULL); } @@ -1240,4 +1276,7 @@ pmc_amd_finalize(struct pmc_mdep *md) free(amd_pcpu, M_PMC); amd_pcpu = NULL; + + free(amd_pmcdesc, M_PMC); + amd_pmcdesc = NULL; } diff --git a/sys/dev/hwpmc/hwpmc_amd.h b/sys/dev/hwpmc/hwpmc_amd.h index 4a8a5f6b6433..4a77ca210f97 100644 --- a/sys/dev/hwpmc/hwpmc_amd.h +++ b/sys/dev/hwpmc/hwpmc_amd.h @@ -197,7 +197,8 @@ #define AMD_PMC_UMC_TO_RDWRMASK(x) (((x) << 8) & AMD_PMC_UMC_RDWRMASK) #define AMD_NPMCS_K8 4 -#define AMD_NPMCS_MAX (AMD_PMC_CORE_MAX + AMD_PMC_L3_MAX + \ +/* Compile-time upper bound; npmcs_total must not exceed this. */ +#define AMD_NPMCS_MAX (AMD_PMC_CORE_MAX + AMD_PMC_L3_MAX + \ AMD_PMC_DF_MAX + AMD_PMC_UMC_MAX) #define AMD_PMC_IS_STOPPED(evsel) ((rdmsr((evsel)) & AMD_PMC_ENABLE) == 0)