Page MenuHomeFreeBSD

hwpmc: add PMU event/group structures and rotation runtime
Needs ReviewPublic

Authored by afscoelho_gmail.com on Jun 18 2026, 7:06 AM.
Tags
None
Referenced Files
F171017217: D57631.id179976.diff
Tue, Sep 8, 5:23 AM
Unknown Object (File)
Sun, Sep 6, 5:38 PM
Unknown Object (File)
Sun, Sep 6, 5:27 AM
Unknown Object (File)
Fri, Sep 4, 6:39 PM
Unknown Object (File)
Fri, Sep 4, 3:56 AM
Unknown Object (File)
Wed, Sep 2, 8:28 AM
Unknown Object (File)
Wed, Sep 2, 3:52 AM
Unknown Object (File)
Tue, Sep 1, 10:34 PM
Subscribers
None

Details

Summary

Add a thin virtual layer (sys/dev/hwpmc/hwpmc_pmu.{h,c}) on top of the
existing hwpmc row programming model, plus the multiplex rotation
back-end that the v0 series left as stubs.

Types (exposed as typedefs per review feedback):

pmu_event_t per-pmc state used to defer HW row binding

			until commit/attach: state, leader flag,
			pre-computed scheduling constraint,
			time-enabled / time-running counters used
			by the multiplex layer.

pmu_group_t leader + sibling list with all-or-none

			commit semantics.  Carries multiplex
			bookkeeping (pg_running, pg_defer_ok,
			pg_assigned, pg_used_rows_mask).

pmc_sched_constraint_t allowed-row bitmask + popcount-as-weight

			+ FIXED/EXCLUSIVE/SHARED flags.  Lower
			weight means more constrained, which the
			assigner uses for most-constrained-first
			greedy placement.

Cross-architecture safety: the grouping/multiplex scheduler is only
implemented where a backend can describe per-event scheduling
constraints (x86/AMD today), so hwpmc_pmu.c and hwpmc_assign.c are
built on amd64/i386 only. hwpmc_pmu.h therefore gates the real entry
points behind HWPMC_PMU_GROUPS (defined for amd64 / i386) and
provides static-inline no-op stubs (pmu_group_on_allocate &c. return
EOPNOTSUPP, the csw/release hooks do nothing) for every other
architecture. The architecture-independent hwpmc_mod.c thus links
unchanged on arm64/arm/powerpc; behaviour there is identical to a
pre-grouping hwpmc. Extending support to another backend is a matter
of adding its constraint provider and defining HWPMC_PMU_GROUPS for it.

Group lifecycle: pmu_group_create / pmu_group_add / pmu_group_commit /
pmu_group_release / pmu_group_lookup. Per-PMC hooks:
pmu_group_on_allocate allocates the pmu_event; pmu_group_on_release
removes the pe from the group TAILQ before freeing it

Rotation runtime:

pmu_pp_schedule_in atomic per-pp placement of a whole group:

				pmu_assign_group, attach every sibling,
				flip pm_state from STOPPED back to
				RUNNING (rotation-evicted PMCs were
				otherwise stuck STOPPED forever).

pmu_pp_schedule_out mirror image: detach, free rows, flip

				pm_state to STOPPED, mark pg_assigned
				false.

pmu_pp_kick_rotate wake the per-pp rotation kthread.
pmu_pp_rotate_thread one kthread per pmc_process; sleeps on

				pp_pmu_rot_thread, ticks every
				rotation_period_us microseconds.

pmu_pp_rotate_one cursor-based round-robin: evict every

				currently scheduled group, then walk
				pp_pmu_groups starting from
				pp_pmu_rot_cursor and schedule_in until
				the first ENOSPC, which pins the next
				tick's cursor.  This avoids the
				FIFO+greedy starvation pattern (small
				groups repeatedly winning the leftover
				slots).

pmu_pp_release_all drain the rotation kthread and sever every

				group still hooked off pp before pp is
				freed.  Wired into pmc_process_exit by
				patch 0004.

The PMC_F_GROUP_MUX commit fallback (over-subscription accepted instead
of returning ENOSPC) is wired up so userland can already opt in via
pmcstat -b.

Signed-off-by: Raghavendra K T <raghavendra.kt@amd.com>

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 76443
Build 73326: arc lint + arc unit

Event Timeline

ali_mashtizadeh.com added inline comments.
sys/dev/hwpmc/hwpmc_pmu.c
100

In your pmc_mod.c code you lookup the userspace identifiers and ensure that these aren't NULL, so it's safe to replace them with an assert.

152

same

403

FreeBSD style wants the variables defined at the top. Alternatively reuse error and use __maybe_unused.

891

Sort local variables largest to smallest

906

Again define all variables at the top of the function but initialize it before use.

sys/dev/hwpmc/hwpmc_pmu.h
127

Unless you have a plan to not require this, I think you should just say it requires the get_sched_contraint call.

143

Why are we hard coding the can_assign_pmc and get_sched_constraint functions? Could we not expose it through the pmc_classdep structure?

That way you remove the #defines and just call the function that will return EOPNOTSUPP if that function pointer in that structure is NULL. Only additional problem I see is you need to lookup the class of the counter.

This revision now requires changes to proceed.Jun 30 2026, 3:47 PM
sys/dev/hwpmc/hwpmc_pmu.c
100

In your pmc_mod.c code you lookup the userspace identifiers and ensure that these aren't NULL, so it's safe to replace them with an assert.

Agree. will remove NULL check. Unless we do some fuzzer test with pmu_group_add function separately, this scenario may not occur.

403

FreeBSD style wants the variables defined at the top. Alternatively reuse error and use __maybe_unused.

Okay. Thinking to reuse error.

891

Sort local variables largest to smallest

Sorry for missing that. Thank you for pointing

906

Again define all variables at the top of the function but initialize it before use.

will do

sys/dev/hwpmc/hwpmc_pmu.h
127

Unless you have a plan to not require this, I think you should just say it requires the get_sched_contraint call.

Thanks for the review.. Agree.

143

Why are we hard coding the can_assign_pmc and get_sched_constraint functions? Could we not expose it through the pmc_classdep structure?

That way you remove the #defines and just call the function that will return EOPNOTSUPP if that function pointer in that structure is NULL. Only additional problem I see is you need to lookup the class of the counter.

Good point. Let me also think about what we should do for ARM/PPC later.

afscoelho_gmail.com updated this revision to Diff 185746.

Update to the rebuilt PerfMonV2 grouping and multiplexing stack.