The branch main has been updated by gallatin: URL: https://cgit.FreeBSD.org/src/commit/?id=194bb58b80c184b8230edef0ed7f292b4bf706b0
commit 194bb58b80c184b8230edef0ed7f292b4bf706b0 Author: Andrew Gallatin <galla...@freebsd.org> AuthorDate: 2025-02-04 22:04:57 +0000 Commit: Andrew Gallatin <galla...@freebsd.org> CommitDate: 2025-02-05 15:26:27 +0000 x86: Fixes for nmi/pmi interrupt sharing - Fix a bug where the semantics of refcount_release() were reversed. This would lead to the nmi interrupt being prematurely masked in the local apic, leading to an out-of-tree profiling tool only getting results the first time it was run. - Stop executing nmi handlers after one claims the interrupt. The core2 hwpmc handler seems to be especially heavy, and running it in addition to vtune's handler caused roughly 50% of the nmi interrupts to be lost (and caused vtune to give worse results). Reviewed by: bojan Sponsored by: Netflix --- sys/x86/x86/cpu_machdep.c | 11 ++++++++--- sys/x86/x86/local_apic.c | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c index 4df652f1f2a8..5b4abfe71642 100644 --- a/sys/x86/x86/cpu_machdep.c +++ b/sys/x86/x86/cpu_machdep.c @@ -65,6 +65,7 @@ #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/pcpu.h> +#include <sys/pmckern.h> #include <sys/rwlock.h> #include <sys/sched.h> #include <sys/smp.h> @@ -955,6 +956,7 @@ nmi_handle_intr(struct trapframe *frame) { int (*func)(struct trapframe *); struct nmi_handler *hp; + int rv; bool handled; #ifdef SMP @@ -965,13 +967,16 @@ nmi_handle_intr(struct trapframe *frame) handled = false; hp = (struct nmi_handler *)atomic_load_acq_ptr( (uintptr_t *)&nmi_handlers_head); - while (hp != NULL) { + while (!handled && hp != NULL) { func = hp->func; if (func != NULL) { atomic_add_int(&hp->running, 1); - if (func(frame) != 0) - handled = true; + rv = func(frame); atomic_subtract_int(&hp->running, 1); + if (rv != 0) { + handled = true; + break; + } } hp = (struct nmi_handler *)atomic_load_acq_ptr( (uintptr_t *)&hp->next); diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 86cbe9a050dc..db9a1eb757de 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -895,7 +895,7 @@ lapic_disable_pcint(void) maxlvt = (lapic_read32(LAPIC_VERSION) & APIC_VER_MAXLVT) >> MAXLVTSHIFT; if (maxlvt < APIC_LVT_PMC) return; - if (refcount_release(&pcint_refcnt)) + if (!refcount_release(&pcint_refcnt)) return; lvts[APIC_LVT_PMC].lvt_masked = 1;