PMCx003 (FpRetSseAvxOps, retired SSE/AVX FLOPs) can increment by more
than 15 in a single cycle, but a core PMC can add at most 15 per cycle,
so its counts are unreliable on a single counter. Starting with family
17h, the hardware can merge an even PMC with the following odd PMC to
count such events correctly ("Large Increment per Cycle Events" in the
PPR). The odd PMC is programmed with the MergeEvent (PMCxFFF), and its
low 16 bits become bits 63:48 of the merged counter.
On family 17h and later, a PMCx003 allocation on a core counter now:
- Requires an even counter whose odd partner is available, and reserves the odd counter for the lifetime of the PMC.
- Programs the odd counter with the MergeEvent before enabling the even counter. In sampling mode, the odd counter is preloaded with 0xffff so the merged counter overflows when the even counter wraps, and it is reloaded on every overflow. In counting mode, it starts at 0.
- Clears the odd counter's event select, value and PerfMonV2 global enable bit on stop and on deconfigure. Deconfigure also covers stalled PMCs, which are not stopped. A leftover MergeEvent would corrupt the next count on the even counter.
On older families, PMCx003 is treated as an ordinary event.
The driver also refuses raw configs that select the MergeEvent, so
only the driver itself programs it. Previously, a raw config could
select the MergeEvent directly, which could corrupt another PMC's count
on the adjacent even counter.
hwpmc has no notion of a PMC that uses two rows, so the odd counter is
reserved in two ways:
- A placeholder struct pmc, marked with the new PMC_F_MERGE_EVENT flag, occupies the odd counter's slot while the merge PMC is configured on a CPU. The interrupt handlers and amd_get_config() skip it, and amd_describe() reports the parent PMC instead.
- The odd row is marked in the row disposition table with the merge PMC's mode, through the new pmc_markrowdisp() and pmc_unmarkrowdisp() helpers. A per-row count of process-mode merges lets the driver refuse other events on that row, because a process-mode PMC can run on any CPU.
As a result, a process-mode merge makes the odd row unavailable to
system-mode PMCs on all CPUs, as any process-mode PMC already does for
its own row.
No changes to libpmc or the userland tools are needed.
Tested legacy path and PerfMonV2 on Zen 4c: counting and sampling in
process and system mode. On PerfMonV2, a merged overflow sets only
the even counter's bit in GLOBAL_STATUS. A raw config selecting
PMCxFFF is refused with EINVAL in process and system mode.
Signed-off-by: Anderson Nascimento <anascime@amd.com>
Sponsored by: AMD