Two pieces:
(1) sys/dev/hwpmc/hwpmc_assign.c
Most-constrained-first greedy assigner. pmu_count_core_hw_slots enumerates global rows that are class-compatible with the leader and pass amd_can_assign_pmc; pmu_assign_group sorts events by weight and binds them all-or-none. Critical detail: the assigner operates in per-class adjri space for pe_cons.pc_allowed_rows / *used_mask / pc_fixed_row, but the framework numbers PMC rows globally. The code converts adjri <-> ri via hwpmc_ri_to_classdep() and pcd->pcd_ri so that amd_can_assign_pmc and pcd_allocate_pmc are always called with the class-relative index they expect. Without this conversion AMD trips its own KASSERT (illegal row index >= amd_npmcs) on Zen, where K8 rows start at global ri=17.
(2) sys/dev/hwpmc/hwpmc_amd.c
Add amd_can_assign_pmc() (factored out of amd_allocate_pmc) and amd_get_sched_constraint() that emits a pmc_sched_constraint_t covering every Zen sub-class (CORE / L3_CACHE / DATA_FABRIC). pc_allowed_rows is built in the per-class adjri namespace as documented in hwpmc_pmu.h. The two new functions are prototyped in hwpmc_pmu.h (alongside the rest of the PMU layer interface) so hwpmc_amd.h needs no change. Other backends (Intel/ARM) continue to return EOPNOTSUPP so legacy non-grouped allocation is unaffected.
Sponsored by: AMD
Signed-off-by: Raghavendra K T <raghavendra.kt@amd.com>