git: 194bb58b80c1 - main - x86: Fixes for nmi/pmi interrupt sharing
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 05 Feb 2025 15:27:08 UTC
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;