Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Feb 2025 15:27:08 GMT
From:      Andrew Gallatin <gallatin@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 194bb58b80c1 - main - x86: Fixes for nmi/pmi interrupt sharing
Message-ID:  <202502051527.515FR8ou081350@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by gallatin:

URL: https://cgit.FreeBSD.org/src/commit/?id=194bb58b80c184b8230edef0ed7f292b4bf706b0

commit 194bb58b80c184b8230edef0ed7f292b4bf706b0
Author:     Andrew Gallatin <gallatin@FreeBSD.org>
AuthorDate: 2025-02-04 22:04:57 +0000
Commit:     Andrew Gallatin <gallatin@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;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502051527.515FR8ou081350>