aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Silva <andasilv@amd.com>2026-08-11 16:16:20 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2026-08-11 16:22:01 +0000
commit66118c3f1011d7852bce8b659899179a83781897 (patch)
tree8597490574842d133e891b4b9bae6ea1cdc9d972
parente85ae6f6a6c0574fdad92b986e37f04f20d5135f (diff)
hwpmc: fix false runcount assertion in user callchain capture
pmc_capture_user_callchain() checks a PMC's runcount before walking the user stack, but reads it without holding the spinlock that protects it. hardclock() can run on the same CPU during the capture and drop the runcount to zero in between, tripping the assertion and panicking INVARIANTS kernels under load. Move the check inside the existing spinlock, right where the code already confirms the sample is still valid. No functional change on kernels built without INVARIANTS. Signed-off-by: Andre Silva <andasilv@amd.com> Reviewed by: mhorne MFC after: 1 week Sponsored by: AMD Differential Revision: https://reviews.freebsd.org/D58571
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 32bb00d671fe..e2d5a044e0b8 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -5016,9 +5016,6 @@ restart:
KASSERT(pm->pm_flags & PMC_F_CALLCHAIN,
("[pmc,%d] Retrieving callchain for PMC that doesn't "
"want it", __LINE__));
- KASSERT(counter_u64_fetch(pm->pm_runcount) > 0,
- ("[pmc,%d] runcount %ju", __LINE__,
- (uintmax_t)counter_u64_fetch(pm->pm_runcount)));
if (ring == PMC_UR) {
counter_u64_add(pmc_stats.pm_merges, 1);
@@ -5044,6 +5041,10 @@ restart:
* Verify that the sample hasn't been dropped in the meantime.
*/
if (ps->ps_nsamples == PMC_USER_CALLCHAIN_PENDING) {
+ KASSERT(counter_u64_fetch(pm->pm_runcount) > 0,
+ ("[pmc,%d] runcount %ju", __LINE__,
+ (uintmax_t)counter_u64_fetch(pm->pm_runcount)));
+
ps->ps_nsamples = nsamples;
/*
* If we couldn't get a sample, simply drop the