From nobody Mon Mar 16 23:39:46 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 4fZWlk2pv0z6VBl4 for ; Mon, 16 Mar 2026 23:39:46 +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 "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fZWlk1YlKz3mb0 for ; Mon, 16 Mar 2026 23:39:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1773704386; 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=IoA12bEESBKanQ/KuzvQLtYM2NGaLouq5YVemj1sWV8=; b=Yla9b6J7F2zmAkC+jUKtLgfBvBQEdTAcunkTBRxkEgeOEPhRBfcc6YE7oAjtTEevbzqMow zwz0iCYQG/6s7xaApMrxPotR/J6y9ta6SLTF1ccLjEU/TpZfycz1nDuFmDx1fZCke14RVC qYZ4Cjz9rhSmh3xF3nzm2eyRr71qYVim3c+fNlfgz1Q759d6iA8ZZuZuROGqWX7SRKZXIo KSBE/isdBGwYsCI5ChBK2zqfr/Tub2FRTCDnBbpdwv6UDTHSXuazSt/jeN9v9Qfeu7lich DLaiPToj+NSlRpGau+NSB08SQQi21f1Wo1ZgcVhOF6JG+Z+CgFDzCGcGRx8rWQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1773704386; a=rsa-sha256; cv=none; b=J5fhaD8Rm6dZtA/6QPMEb0BM9L5vmyzh7A8+mAkVeTZeotwkTjk6M60NtiBiNU1RJap30X 3StcqV8hMbeei/eBPOGVLznOLiD6MX1Pb+9gzJRFgfCjiG8dz0p+1jUTMk4HqqGcQ7I/FO mUyjHhyuDsNr7CIjtJSWmNv0ZafjeFLA0R5QGg3RQasLKS27Wratrua8WlidoiQHwQKG9p 9+A8jWBkkAqsFxLq6OZiOsWB1XDaGI9RXijlog8HG8tHxWx493gN1WobCDnaSS7pLEclz6 r8aRsW2/vhEKE8pBJZA7O3wB44mZkLSU8cLOJcfSRkGEGfVeiPaJGS4G86yfAQ== 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=1773704386; 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=IoA12bEESBKanQ/KuzvQLtYM2NGaLouq5YVemj1sWV8=; b=WKoS2LWdciPvqeqaSEW2pdrkTgeO5imQrod3e14OA7BAXRR0Y15DvQSS2HzZe43i5tMx3I x7QIoyoHnXrrQnAkDVb1CRwbuakDQlv2+JimrtAP/Lk8bbZW7ppFWNe50v0Dtm/MVArSJP ywP2EsTdK54YrPLhxivwoYXq0WMvZvvKzOuUYVWA+bF+hmdbKFUrs2XohqLEWPeJUdWFKo jQgqj+QV5tTUzADvpbVgTfjeEWOaXew1YX2jcOaGL7x3rQ3NjSQAxewGHUgug8xXfTSJAt cGbySJm4jkEDJwXycaZ1SZelmqib/WW3iyw4e7g4OG32E2oURMxBURbDCAPFRQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fZWlk0g9rzxGD for ; Mon, 16 Mar 2026 23:39:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 226fd by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 16 Mar 2026 23:39:46 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Ali Mashtizadeh From: Mitchell Horne Subject: git: 44a983d249d0 - main - libpmc: Query hwpmc for caps 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 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: 44a983d249d05d932b6cff333f130baf70febc22 Auto-Submitted: auto-generated Date: Mon, 16 Mar 2026 23:39:46 +0000 Message-Id: <69b894c2.226fd.416425cf@gitrepo.freebsd.org> The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=44a983d249d05d932b6cff333f130baf70febc22 commit 44a983d249d05d932b6cff333f130baf70febc22 Author: Ali Mashtizadeh AuthorDate: 2026-03-01 22:08:30 +0000 Commit: Mitchell Horne CommitDate: 2026-03-16 23:31:15 +0000 libpmc: Query hwpmc for caps This change allows for fine-grained capabilities per counter index. This is particularly useful for AMD where subclasses are not exposed to the general PMC code, but other architectures also have asymmetric behaviors when it comes to specific counter indices. A new PMC_OP_GETCAPS op is added to the hwpmc(4) ioctl interface. Reviewed by: mhorne Sponsored by: Netflix Pull Request: https://github.com/freebsd/freebsd-src/pull/2058 --- lib/libpmc/libpmc.c | 19 +++++++++---------- share/man/man4/hwpmc.4 | 4 ++++ sys/dev/hwpmc/hwpmc_amd.c | 15 +++++++++++++++ sys/dev/hwpmc/hwpmc_mod.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ sys/sys/pmc.h | 15 ++++++++++++++- 5 files changed, 87 insertions(+), 11 deletions(-) diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c index 6be91a7501fe..ceba40aa7b39 100644 --- a/lib/libpmc/libpmc.c +++ b/lib/libpmc/libpmc.c @@ -1211,17 +1211,16 @@ pmc_attach(pmc_id_t pmc, pid_t pid) int pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) { - unsigned int i; - enum pmc_class cl; + struct pmc_op_caps args; + int status; - cl = PMC_ID_TO_CLASS(pmcid); - for (i = 0; i < cpu_info.pm_nclass; i++) - if (cpu_info.pm_classes[i].pm_class == cl) { - *caps = cpu_info.pm_classes[i].pm_caps; - return (0); - } - errno = EINVAL; - return (-1); + args.pm_pmcid = pmcid; + args.pm_caps = 0; + + status = PMC_CALL(PMC_OP_GETCAPS, &args); + *caps = args.pm_caps; + + return (status); } int diff --git a/share/man/man4/hwpmc.4 b/share/man/man4/hwpmc.4 index 54a251dcca76..1ab690e5009c 100644 --- a/share/man/man4/hwpmc.4 +++ b/share/man/man4/hwpmc.4 @@ -325,6 +325,10 @@ This operation returns to the caller after the write operation has returned. The returned error code reflects any pending error state inside .Nm . +.It Dv PMC_OP_GETCAPS +Retrieve the capabilities associated with a specific PMC counter. +Some capabilities may be limited to specific indices (i.e., not available +across all counters within a class). .It Dv PMC_OP_GETCPUINFO Retrieve information about the highest possible CPU number for the system, and the number of hardware performance monitoring counters available per CPU. diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index c27d93995d59..51505bfcff37 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -702,6 +702,20 @@ amd_get_msr(int ri, uint32_t *msr) return (0); } +/* + * Return the capabilities of the given PMC. + */ +static int +amd_get_caps(int ri, uint32_t *caps) +{ + KASSERT(ri >= 0 && ri < amd_npmcs, + ("[amd,%d] ri %d out of range", __LINE__, ri)); + + *caps = amd_pmcdesc[ri].pm_descr.pd_caps; + + return (0); +} + /* * Processor-dependent initialization. */ @@ -958,6 +972,7 @@ pmc_amd_initialize(void) pcd->pcd_start_pmc = amd_start_pmc; pcd->pcd_stop_pmc = amd_stop_pmc; pcd->pcd_write_pmc = amd_write_pmc; + pcd->pcd_get_caps = amd_get_caps; pmc_mdep->pmd_cputype = cputype; pmc_mdep->pmd_intr = amd_intr; diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 1fa021429c5a..fb1fdf832398 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -4538,6 +4538,51 @@ pmc_syscall_handler(struct thread *td, void *syscall_args) } break; + /* + * Get the PMC capabilities + */ + + case PMC_OP_GETCAPS: + { + struct pmc_op_caps c; + struct pmc *pm; + struct pmc_classdep *pcd; + pmc_id_t pmcid; + int adjri, ri; + + PMC_DOWNGRADE_SX(); + + if ((error = copyin(arg, &c, sizeof(c))) != 0) + break; + + pmcid = c.pm_pmcid; + + if ((error = pmc_find_pmc(pmcid, &pm)) != 0) + break; + + KASSERT(pmcid == pm->pm_id, + ("[pmc,%d] pmc id %x != pmcid %x", __LINE__, + pm->pm_id, pmcid)); + + ri = PMC_TO_ROWINDEX(pm); + pcd = pmc_ri_to_classdep(md, ri, &adjri); + + /* + * If PMC class has no GETCAPS return the class capabilities + * otherwise get the per counter capabilities. + */ + if (pcd->pcd_get_caps == NULL) { + c.pm_caps = pcd->pcd_caps; + } else { + error = (*pcd->pcd_get_caps)(adjri, &c.pm_caps); + if (error < 0) + break; + } + + if ((error = copyout(&c, arg, sizeof(c))) < 0) + break; + } + break; default: error = EINVAL; diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index 7640a9b96c84..244a18e90c39 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -346,7 +346,8 @@ enum pmc_event { __PMC_OP(PMCSTOP, "Stop a PMC") \ __PMC_OP(WRITELOG, "Write a cookie to the log file") \ __PMC_OP(CLOSELOG, "Close log file") \ - __PMC_OP(GETDYNEVENTINFO, "Get dynamic events list") + __PMC_OP(GETDYNEVENTINFO, "Get dynamic events list") \ + __PMC_OP(GETCAPS, "Get capabilities") enum pmc_ops { #undef __PMC_OP @@ -638,6 +639,17 @@ struct pmc_op_getdyneventinfo { struct pmc_dyn_event_descr pm_events[PMC_EV_DYN_COUNT]; }; +/* + * OP GETCAPS + * + * Retrieve the PMC capabilties flags for this type of counter. + */ + +struct pmc_op_caps { + pmc_id_t pm_pmcid; /* allocated pmc id */ + uint32_t pm_caps; /* capabilities */ +}; + #ifdef _KERNEL #include @@ -1040,6 +1052,7 @@ struct pmc_classdep { /* description */ int (*pcd_describe)(int _cpu, int _ri, struct pmc_info *_pi, struct pmc **_ppmc); + int (*pcd_get_caps)(int _ri, uint32_t *_caps); /* class-dependent initialization & finalization */ int (*pcd_pcpu_init)(struct pmc_mdep *_md, int _cpu);