hwpmc: fix a race between amd_stop_pmc and amd_intr

It is possible that wrmsr in amd_stop_pmc() causes an overflow in a counter
that it disables.  In that case a non-maskable interrupt is generated.  The
interrupt handler code was written in such a way that it would re-enable the
counter.  That would lead to an unexpected interrupt later on.

This problem was easy to reproduce with
$ pmcstat -T -P instructions -t $pid
if the target process is sufficiently busy and there are context switches from
time to time.  There would be a lot of interrupts to "race" with amd_stop_pmc()
called during the context switches.  The problem affected only AMD processors.

While there, trace whether amd_intr() claimed an interrupt.

Reviewed by:	jhb
MFC after:	2 weeks
This commit is contained in:
Andriy Gapon 2016-10-30 09:38:10 +00:00
parent c82bd4484c
commit 3c1f73b18d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=308101

View file

@ -689,12 +689,13 @@ amd_intr(int cpu, struct trapframe *tf)
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
TRAPF_USERMODE(tf));
if (error == 0)
wrmsr(evsel, config | AMD_PMC_ENABLE);
wrmsr(evsel, config);
}
atomic_add_int(retval ? &pmc_stats.pm_intr_processed :
&pmc_stats.pm_intr_ignored, 1);
PMCDBG1(MDP,INT,2, "retval=%d", retval);
return (retval);
}