The branch main has been updated by bnovkov:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=04e832672159cae412e8984e0b0cabfa6e7428b7

commit 04e832672159cae412e8984e0b0cabfa6e7428b7
Author:     Bojan Novković <bnov...@freebsd.org>
AuthorDate: 2024-12-15 14:00:19 +0000
Commit:     Bojan Novković <bnov...@freebsd.org>
CommitDate: 2024-12-15 15:39:36 +0000

    x86: Allow sharing of perfomance counter interrupts
    
    This patch refactors the Performance Counter interrupt setup code to
    allow sharing the interrupt line between multiple drivers.
    More specifically, Performance Counter interrupts are used by both
    hwpmc(4) and hwt(4)'s upcoming Intel Processor Trace backend.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D46420
---
 sys/dev/hwpmc/hwpmc_core.c |  4 ++--
 sys/dev/hwpmc/hwpmc_x86.c  |  4 ++--
 sys/x86/include/apicvar.h  |  6 +++---
 sys/x86/x86/local_apic.c   | 33 ++++++++++++++-------------------
 4 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index bf224ded126f..83784b93718e 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -1051,7 +1051,7 @@ core_intr(struct trapframe *tf)
                counter_u64_add(pmc_stats.pm_intr_ignored, 1);
 
        if (found_interrupt)
-               lapic_reenable_pmc();
+               lapic_reenable_pcint();
 
        return (found_interrupt);
 }
@@ -1150,7 +1150,7 @@ core2_intr(struct trapframe *tf)
                counter_u64_add(pmc_stats.pm_intr_ignored, 1);
 
        if (found_interrupt)
-               lapic_reenable_pmc();
+               lapic_reenable_pcint();
 
        /*
         * Reenable all non-stalled PMCs.
diff --git a/sys/dev/hwpmc/hwpmc_x86.c b/sys/dev/hwpmc/hwpmc_x86.c
index 1d04a6610674..54cc919eec30 100644
--- a/sys/dev/hwpmc/hwpmc_x86.c
+++ b/sys/dev/hwpmc/hwpmc_x86.c
@@ -242,7 +242,7 @@ pmc_md_initialize(void)
                return (NULL);
 
        /* disallow sampling if we do not have an LAPIC */
-       if (md != NULL && !lapic_enable_pmc())
+       if (md != NULL && !lapic_enable_pcint())
                for (i = 0; i < md->pmd_nclass; i++) {
                        if (i == PMC_CLASS_INDEX_SOFT)
                                continue;
@@ -256,7 +256,7 @@ void
 pmc_md_finalize(struct pmc_mdep *md)
 {
 
-       lapic_disable_pmc();
+       lapic_disable_pcint();
        if (cpu_vendor_id == CPU_VENDOR_AMD ||
            cpu_vendor_id == CPU_VENDOR_HYGON)
                pmc_amd_finalize(md);
diff --git a/sys/x86/include/apicvar.h b/sys/x86/include/apicvar.h
index fc9bb0123539..c537d0ee0cdd 100644
--- a/sys/x86/include/apicvar.h
+++ b/sys/x86/include/apicvar.h
@@ -231,9 +231,9 @@ void        apic_enable_vector(u_int apic_id, u_int vector);
 void   apic_disable_vector(u_int apic_id, u_int vector);
 void   apic_free_vector(u_int apic_id, u_int vector, u_int irq);
 void   lapic_calibrate_timer(void);
-int    lapic_enable_pmc(void);
-void   lapic_disable_pmc(void);
-void   lapic_reenable_pmc(void);
+int    lapic_enable_pcint(void);
+void   lapic_disable_pcint(void);
+void   lapic_reenable_pcint(void);
 void   lapic_enable_cmc(void);
 int    lapic_enable_mca_elvt(void);
 void   lapic_ipi_raw(register_t icrlo, u_int dest);
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 6a913883cc5c..86cbe9a050dc 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -35,7 +35,6 @@
 
 #include <sys/cdefs.h>
 #include "opt_atpic.h"
-#include "opt_hwpmc_hooks.h"
 
 #include "opt_ddb.h"
 
@@ -50,6 +49,7 @@
 #include <sys/mutex.h>
 #include <sys/pcpu.h>
 #include <sys/proc.h>
+#include <sys/refcount.h>
 #include <sys/sched.h>
 #include <sys/smp.h>
 #include <sys/sysctl.h>
@@ -206,6 +206,7 @@ static uint64_t lapic_ipi_wait_mult;
 static int __read_mostly lapic_ds_idle_timeout = 1000000;
 #endif
 unsigned int max_apic_id;
+static int pcint_refcnt = 0;
 
 SYSCTL_NODE(_hw, OID_AUTO, apic, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "APIC options");
@@ -809,20 +810,19 @@ lapic_intrcnt(void *dummy __unused)
 SYSINIT(lapic_intrcnt, SI_SUB_INTR, SI_ORDER_MIDDLE, lapic_intrcnt, NULL);
 
 void
-lapic_reenable_pmc(void)
+lapic_reenable_pcint(void)
 {
-#ifdef HWPMC_HOOKS
        uint32_t value;
 
+       if (refcount_load(&pcint_refcnt) == 0)
+               return;
        value = lapic_read32(LAPIC_LVT_PCINT);
        value &= ~APIC_LVT_M;
        lapic_write32(LAPIC_LVT_PCINT, value);
-#endif
 }
 
-#ifdef HWPMC_HOOKS
 static void
-lapic_update_pmc(void *dummy)
+lapic_update_pcint(void *dummy)
 {
        struct lapic *la;
 
@@ -830,7 +830,6 @@ lapic_update_pmc(void *dummy)
        lapic_write32(LAPIC_LVT_PCINT, lvt_mode(la, APIC_LVT_PMC,
            lapic_read32(LAPIC_LVT_PCINT)));
 }
-#endif
 
 void
 lapic_calibrate_timer(void)
@@ -858,9 +857,8 @@ lapic_calibrate_timer(void)
 }
 
 int
-lapic_enable_pmc(void)
+lapic_enable_pcint(void)
 {
-#ifdef HWPMC_HOOKS
        u_int32_t maxlvt;
 
 #ifdef DEV_ATPIC
@@ -873,21 +871,18 @@ lapic_enable_pmc(void)
        maxlvt = (lapic_read32(LAPIC_VERSION) & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
        if (maxlvt < APIC_LVT_PMC)
                return (0);
-
+       if (refcount_acquire(&pcint_refcnt) > 0)
+               return (1);
        lvts[APIC_LVT_PMC].lvt_masked = 0;
 
        MPASS(mp_ncpus == 1 || smp_started);
-       smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
+       smp_rendezvous(NULL, lapic_update_pcint, NULL, NULL);
        return (1);
-#else
-       return (0);
-#endif
 }
 
 void
-lapic_disable_pmc(void)
+lapic_disable_pcint(void)
 {
-#ifdef HWPMC_HOOKS
        u_int32_t maxlvt;
 
 #ifdef DEV_ATPIC
@@ -900,15 +895,15 @@ lapic_disable_pmc(void)
        maxlvt = (lapic_read32(LAPIC_VERSION) & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
        if (maxlvt < APIC_LVT_PMC)
                return;
-
+       if (refcount_release(&pcint_refcnt))
+               return;
        lvts[APIC_LVT_PMC].lvt_masked = 1;
 
 #ifdef SMP
        /* The APs should always be started when hwpmc is unloaded. */
        KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early"));
 #endif
-       smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
-#endif
+       smp_rendezvous(NULL, lapic_update_pcint, NULL, NULL);
 }
 
 static int

Reply via email to