git: 04e832672159 - main - x86: Allow sharing of perfomance counter interrupts
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 15 Dec 2024 15:40:36 UTC
The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=04e832672159cae412e8984e0b0cabfa6e7428b7 commit 04e832672159cae412e8984e0b0cabfa6e7428b7 Author: Bojan Novković <bnovkov@FreeBSD.org> AuthorDate: 2024-12-15 14:00:19 +0000 Commit: Bojan Novković <bnovkov@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