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;
 

Reply via email to