Process one NMI interrupt per handler invocation as the processor

'buffers' pending NMIs from multiple interrupting PMCs and delivers
them serially.

Reported by:	 Olivier Crameri <olivier.crameri@epfl.ch>
MFC after:	3 days
This commit is contained in:
Joseph Koshy 2005-09-12 15:55:44 +00:00
parent 533dcdacf1
commit bebaef4a3d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=150050

View File

@ -693,9 +693,14 @@ amd_intr(int cpu, uintptr_t eip, int usermode)
* and which has a valid 'struct pmc' association
*
* If found, we call a helper to process the interrupt.
*
* If multiple PMCs interrupt at the same time, the AMD64
* processor appears to deliver as many NMIs as there are
* outstanding PMC interrupts. Thus we need to only process
* one interrupt at a time.
*/
for (i = 0; i < AMD_NPMCS-1; i++) {
for (i = 0; retval == 0 && i < AMD_NPMCS-1; i++) {
ri = i + 1; /* row index; TSC is at ri == 0 */
@ -712,6 +717,8 @@ amd_intr(int cpu, uintptr_t eip, int usermode)
continue;
}
retval = 1; /* found an interrupting PMC */
/* stop the PMC, reload count */
evsel = AMD_PMC_EVSEL_0 + i;
perfctr = AMD_PMC_PERFCTR_0 + i;
@ -726,12 +733,10 @@ amd_intr(int cpu, uintptr_t eip, int usermode)
wrmsr(evsel, config & ~AMD_PMC_ENABLE);
wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
/* restart if there was no error during logging */
/* restart the counter if there was no error during logging */
error = pmc_process_interrupt(cpu, pm, eip, usermode);
if (error == 0)
wrmsr(evsel, config | AMD_PMC_ENABLE);
retval = 1; /* found an interrupting PMC */
}
atomic_add_int(retval ? &pmc_stats.pm_intr_processed :