diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c --- a/sys/dev/hwpmc/hwpmc_core.c +++ b/sys/dev/hwpmc/hwpmc_core.c @@ -1051,7 +1051,7 @@ 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 @@ 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 --- a/sys/dev/hwpmc/hwpmc_x86.c +++ b/sys/dev/hwpmc/hwpmc_x86.c @@ -242,7 +242,7 @@ 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 @@ 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 --- a/sys/x86/include/apicvar.h +++ b/sys/x86/include/apicvar.h @@ -229,9 +229,9 @@ 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 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -36,6 +36,7 @@ #include #include "opt_atpic.h" #include "opt_hwpmc_hooks.h" +#include "opt_hwt_hooks.h" #include "opt_ddb.h" @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -206,6 +208,7 @@ 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 +812,19 @@ 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 +832,6 @@ lapic_write32(LAPIC_LVT_PCINT, lvt_mode(la, APIC_LVT_PMC, lapic_read32(LAPIC_LVT_PCINT))); } -#endif void lapic_calibrate_timer(void) @@ -858,9 +859,8 @@ } int -lapic_enable_pmc(void) +lapic_enable_pcint(void) { -#ifdef HWPMC_HOOKS u_int32_t maxlvt; #ifdef DEV_ATPIC @@ -873,21 +873,18 @@ 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 +897,15 @@ 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