From nobody Mon Jul 20 10:25:13 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 4h3c8v4102z6ljx7 for ; Mon, 20 Jul 2026 10:25:19 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h3c8v2CR5z45Cq for ; Mon, 20 Jul 2026 10:25:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1784543119; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=J23DC2I44bJ04uenN1P6HALpLRjH354DUgM8ebiaB+o=; b=AbT3Emnt266edOlnHlBpc0V0jrZl7aTVTKv9VsVrs81kSd3nD4Ni0ZkVf7Cj76B8fQ0/ev +GN0fphqyZv1dW3SSt4AeK5WAQHmcaisNrn3RBrrRA4ng0bxMqJpsFIwjtINoX01jPIIfF HxYnNXmxCr0QDqHl9+iMknSsgdy9xpuH5v0A20Hh8sOpWoIlw4myklY2WXU69yUPEkl7IL Tww72TLAJG+K+ZJJRDoo5sO7E/9bBs5l5FMgiaFRNI0tpcE63UFJxPKUJNAOiAcm2mv4hF LaRk8grClRP9VgwO43SC2Wu3VF8cHJplRsQWJfy1vviLQ6xL93nfzPW6KENqpA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1784543119; a=rsa-sha256; cv=none; b=BmWq4H4bV/ZBNzEBSoqgnq+jE8EsUlxZP5FqRxr5zOu5HTv4gGTP5u2aRZtBRMYOG/W29W bM2z+lV5kfzLpzrS/840TiGvwGkOBukcEmx1DQ8mOJ5X99fUyukfYZIwLF3N0ThAuWeRun eKZzbNLyTv5IgX5JgJjyuvriE9E7Sx9kRR6BCWYqANGoV9FwbXAbpKtOUb+oVuYiLvhZLJ KfIJFDwzwIS6IVM1l8V/6Ro+gqd7uTDEcYWbyGWbiaPr8l64MrK3bHKFJNeWEU5URasdjH ygdPMeZzxUyAp0hGk6B3YRs46jUj2CnX4a1vIc+HgcdKNZ5j26KT+0xTgbKrLA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1784543119; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=J23DC2I44bJ04uenN1P6HALpLRjH354DUgM8ebiaB+o=; b=Q6ArcPutypjurTtQjgTJM0ZH9peiy+qjkdsLW1/f5t20wDOkDsCmkELEJE9Hpqq5utVKDB ZyVdtZFDDzJkibRkiEboQK46dhQbkPrGkzm9s14iuRVjtnwE1LhxzPCL8ATKncZ4odrIy4 QvC/cANA4Csf9ANQTetT6zl3oASPmlTfCDuxQmtC8uQkJI+/Ab+L0NJTg34cs0mT3KmWtt 8llerX48c+f6qSd9NDuJDsuA5oniAPVRsQyLq9dqXzH8rzk5Vc81DMP5fT0qJnbwg63gn2 GrdB0OmVKeXYuDhR8uEbGncoLmjfdgcMFFPPr5IZ25o1H4tTLnLXjmtEbg4Rzw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h3c8v1Hhtzx8G for ; Mon, 20 Jul 2026 10:25:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3127c by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 20 Jul 2026 10:25:13 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Alexander Leidinger Subject: git: e42703f5c4b2 - main - hwpmc: handle counter wraparound for process-mode counting PMCs 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: netchild X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e42703f5c4b2d3a869b17e2cb8670f1b6359c8cf Auto-Submitted: auto-generated Date: Mon, 20 Jul 2026 10:25:13 +0000 Message-Id: <6a5df789.3127c.4e973f46@gitrepo.freebsd.org> The branch main has been updated by netchild: URL: https://cgit.FreeBSD.org/src/commit/?id=e42703f5c4b2d3a869b17e2cb8670f1b6359c8cf commit e42703f5c4b2d3a869b17e2cb8670f1b6359c8cf Author: Alexander Leidinger AuthorDate: 2026-07-19 07:38:52 +0000 Commit: Alexander Leidinger CommitDate: 2026-07-20 10:24:18 +0000 hwpmc: handle counter wraparound for process-mode counting PMCs The accumulated count of a process-mode counting PMC is kept in a 64-bit software counter and seeded into the hardware counter at every context switch in. Hardware counters are narrower than that - each PMC class discovers and records its own counter width, e.g. 48 bits on current x86 (queried from CPUID on Intel, architectural on AMD) - so once the accumulated count approaches the end of the hardware counter range, the counter wraps during a time slice and the value read back at switch out is smaller than the value seeded. The increment was computed assuming a full 64-bit counter: on INVARIANTS kernels a long enough counting run panics with "negative increment" the moment the accumulated count first crosses the hardware counter range, and on other kernels the totals silently lose a full counter range per wrap. Compute the increment modulo the per-class hardware counter width instead, in both places that accumulate switch-out deltas. Reviewed by: adrian MFC after: 2 weeks Assisted-by: Claude Code (Fable 5) Differential Revision: https://reviews.freebsd.org/D58340 --- sys/dev/hwpmc/hwpmc_mod.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 9533cb81b4a1..086a05657cfe 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -1594,6 +1594,24 @@ pmc_process_csw_in(struct thread *td) critical_exit(); } +/* + * Compute the change in a counter's value since it was last written. + * The hardware counter is only pcd_width bits wide and wraps around, + * while the value seeded into it may occupy the full 64-bit range, so + * take the difference modulo the counter width. + */ +static pmc_value_t +pmc_delta(const struct pmc_classdep *pcd, pmc_value_t newvalue, + pmc_value_t oldvalue) +{ + pmc_value_t delta; + + delta = newvalue - oldvalue; + if (pcd->pcd_width < 64) + delta &= ((pmc_value_t)1 << pcd->pcd_width) - 1; + return (delta); +} + /* * Thread context switch OUT. */ @@ -1606,8 +1624,7 @@ pmc_process_csw_out(struct thread *td) struct pmc_process *pp; struct pmc_thread *pt = NULL; struct proc *p; - pmc_value_t newvalue; - int64_t tmp; + pmc_value_t newvalue, tmp; enum pmc_mode mode; int cpu; u_int adjri, ri; @@ -1745,23 +1762,19 @@ pmc_process_csw_out(struct thread *td) } mtx_pool_unlock_spin(pmc_mtxpool, pm); } else { - tmp = newvalue - PMC_PCPU_SAVED(cpu, ri); + /* + * For counting process-virtual PMCs, the + * hardware counter's value increases + * monotonically modulo the counter width; + * pmc_delta() recovers the increment even + * when the counter wrapped during the run. + */ + tmp = pmc_delta(pcd, newvalue, + PMC_PCPU_SAVED(cpu, ri)); PMCDBG3(CSW,SWO,1,"cpu=%d ri=%d tmp=%jd (count)", cpu, ri, tmp); - /* - * For counting process-virtual PMCs, - * we expect the count to be - * increasing monotonically, modulo a 64 - * bit wraparound. - */ - KASSERT(tmp >= 0, - ("[pmc,%d] negative increment cpu=%d " - "ri=%d newvalue=%jx saved=%jx " - "incr=%jx", __LINE__, cpu, ri, - newvalue, PMC_PCPU_SAVED(cpu, ri), tmp)); - mtx_pool_lock_spin(pmc_mtxpool, pm); pm->pm_gv.pm_savedvalue += tmp; pp->pp_pmcs[ri].pp_pmcval += tmp; @@ -5177,7 +5190,8 @@ pmc_process_exit(void *arg __unused, struct proc *p) if (PMC_TO_MODE(pm) == PMC_MODE_TC) { pcd->pcd_read_pmc(cpu, adjri, pm, &newvalue); - tmp = newvalue - PMC_PCPU_SAVED(cpu, ri); + tmp = pmc_delta(pcd, newvalue, + PMC_PCPU_SAVED(cpu, ri)); mtx_pool_lock_spin(pmc_mtxpool, pm); pm->pm_gv.pm_savedvalue += tmp;