When a process-mode PMC is released, pmc_release_pmc_descriptor() marks
it PMC_STATE_DELETED and waits for pm_runcount to reach zero. That is
not enough:
- pmc_process_csw_in() checks pm_state and only then increments pm_runcount. A release that runs in between sees a zero runcount and frees the PMC, which the switch-in then loads.
- pmc_process_csw_out() decrements pm_runcount before it deconfigures the PMC, and still uses it in between. A release can free the PMC in that window.
Both paths run in critical sections. After the runcount reaches zero,
quiesce every CPU with quiesce_all_cpus(PDROP), which forces each CPU
out of any critical section it is in, and repeat until the runcount is
zero after a quiesce. A switch-in that starts afterwards sees
PMC_STATE_DELETED. The cost is paid only on release, and the context
switch paths are unchanged.
The ordering dates back to the original hwpmc import. The switch-in
race triggers a "pmc has non-zero run count" panic under INVARIANTS
when a PMC is released while its target thread switches in and out
frequently.
Signed-off-by: Anderson Nascimento <anascime@amd.com>
Sponsored by: AMD