git: 4b267d4e4f6a - main - hwpmc: fix stopping process PMCs on exit with PerfMonV2
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 02 Oct 2026 13:58:53 UTC
The branch main has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=4b267d4e4f6a6cd7bd08b9c4854fcb26fab8c18c
commit 4b267d4e4f6a6cd7bd08b9c4854fcb26fab8c18c
Author: Andre Silva <andasilv@amd.com>
AuthorDate: 2026-10-02 13:55:26 +0000
Commit: Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2026-10-02 13:55:41 +0000
hwpmc: fix stopping process PMCs on exit with PerfMonV2
Since 9d3064010590, pmc_process_exit() calls pmc_process_csw_stop_all()
first. That clears pps_cpustate for every virtual PMC on the CPU, so the
exit loop then skips the stop and the final read.
On AMD PerfMonV2 this has two effects:
- The count from the last time slice is lost. A process that never
switches out before exit reports 0 with pmcstat -p.
- The EVSEL enable bit stays set. After kldunload, the next kldload
sees it and says "PMCs maybe in use by firmware!".
It is not required that pmc_process_csw_stop_all() should touch the
ppc_cpustate field at all; remove this to fix the issues.
Reviewed by: mhorne
Fixes: 9d3064010590 ("hwpmc_amd: add PerfMonV2 global-control path")
Sponsored by: AMD
Differential Revision: https://reviews.freebsd.org/D60141
---
sys/dev/hwpmc/hwpmc_mod.c | 29 -----------------------------
1 file changed, 29 deletions(-)
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 1a333e137d0a..7db73b5c78c9 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -248,7 +248,6 @@ static void pmc_post_callchain_callback(void);
static void pmc_process_allproc(struct pmc *pm);
static void pmc_process_csw_in(struct thread *td);
static void pmc_process_csw_out(struct thread *td);
-static void pmc_process_csw_out_prepare(int cpu);
static void pmc_process_csw_start_all(int cpu);
static void pmc_process_csw_stop_all(int cpu);
static void pmc_process_exec(struct thread *td,
@@ -1449,8 +1448,6 @@ pmc_process_csw_stop_all(int cpu)
struct pmc_classdep *pcd;
u_int class;
- pmc_process_csw_out_prepare(cpu);
-
for (class = 0; class < md->pmd_nclass; class++) {
pcd = &md->pmd_classdep[class];
if (pcd->pcd_stop_all != NULL)
@@ -1458,32 +1455,6 @@ pmc_process_csw_stop_all(int cpu)
}
}
-/*
- * Mark virtual PMCs stopped, before you close hardware gates.
- */
-static void
-pmc_process_csw_out_prepare(int cpu)
-{
- struct pmc *pm;
- struct pmc_classdep *pcd;
- u_int class;
- int adjri;
-
- for (class = 0; class < md->pmd_nclass; class++) {
- pcd = &md->pmd_classdep[class];
- if (pcd->pcd_stop_all == NULL)
- continue;
- for (adjri = 0; adjri < pcd->pcd_num; adjri++) {
- pm = NULL;
- (void)pcd->pcd_get_config(cpu, adjri, &pm);
- if (pm == NULL ||
- !PMC_IS_VIRTUAL_MODE(PMC_TO_MODE(pm)))
- continue;
- pm->pm_pcpu_state[cpu].pps_cpustate = 0;
- }
- }
-}
-
/*
* Thread context switch IN.
*/