git: 6d9f435739e5 - main - hwpmc: fix leak of IBS per-CPU array on unload
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 22 Sep 2026 14:01:27 UTC
The branch main has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=6d9f435739e5fb604f452d03ad7f2eb280bfc968
commit 6d9f435739e5fb604f452d03ad7f2eb280bfc968
Author: Paulo Fragoso <paulo@nlink.com.br>
AuthorDate: 2026-09-22 14:00:31 +0000
Commit: Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2026-09-22 14:01:24 +0000
hwpmc: fix leak of IBS per-CPU array on unload
pmc_ibs_initialize() allocates the ibs_pcpu[] pointer array, and
pmc_ibs_finalize() exists to free it, but pmc_ibs_finalize() is
never called. Every hwpmc unload on a CPU with IBS therefore leaks
one pmc_cpu_max()-sized pointer array.
Call pmc_ibs_finalize() from pmc_amd_finalize(), alongside the RAPL,
TSC and perf classes. IBS is only initialized on CPUs that support
it, so make pmc_ibs_finalize() return early when ibs_pcpu is NULL,
making it safe to call when the class was skipped at initialize
time, as pmc_rapl_finalize() already is.
Tested on an AMD Ryzen 5 5600X (Zen 3, 12 threads) with INVARIANTS.
Before the change, each kldload/kldunload cycle leaked one 96-byte
M_PMC allocation, and DTrace showed the ibs_pcpu[] allocation from
pmc_ibs_initialize() as the only one never freed. After the change,
50 load/unload cycles leave M_PMC InUse and MemUse unchanged, and
every allocation made at load is freed at unload.
Reviewed by: mhorne
Fixes: e51ef8ae490f ("hwpmc: Initial support for AMD IBS")
Sponsored by: NLINK (https://nlink.com.br), Recife, Brazil
Differential Revision: https://reviews.freebsd.org/D59881
---
sys/dev/hwpmc/hwpmc_amd.c | 2 ++
sys/dev/hwpmc/hwpmc_ibs.c | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index 232c59aea3bf..77d4a4230e49 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -1270,6 +1270,8 @@ pmc_amd_finalize(struct pmc_mdep *md)
pmc_perf_finalize(md);
+ pmc_ibs_finalize(md);
+
for (int i = 0; i < pmc_cpu_max(); i++)
KASSERT(amd_pcpu[i] == NULL,
("[amd,%d] non-null pcpu cpu %d", __LINE__, i));
diff --git a/sys/dev/hwpmc/hwpmc_ibs.c b/sys/dev/hwpmc/hwpmc_ibs.c
index ce9e038e5d0b..17c3495f6a79 100644
--- a/sys/dev/hwpmc/hwpmc_ibs.c
+++ b/sys/dev/hwpmc/hwpmc_ibs.c
@@ -918,6 +918,10 @@ pmc_ibs_finalize(struct pmc_mdep *md)
{
PMCDBG0(MDP, INI, 1, "ibs-finalize");
+ /* Safe even if the IBS class was skipped at initialize time. */
+ if (ibs_pcpu == NULL)
+ return;
+
for (int i = 0; i < pmc_cpu_max(); i++)
KASSERT(ibs_pcpu[i] == NULL,
("[ibs,%d] non-null pcpu cpu %d", __LINE__, i));