Index: sys/arm64/arm64/pmu_enable.c =================================================================== --- /dev/null +++ sys/arm64/arm64/pmu_enable.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2020, Juniper Networks, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#define ARMV8_PMCR_MASK 0x3f +#define ARMV8_PMCR_E (1 << 0) /* Enable all counters */ +#define ARMV8_PMCR_P (1 << 1) /* Reset all counters */ +#define ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */ +#define ARMV8_PMCR_D (1 << 3) /* CCNT counts every 64th cpu cycle */ +#define ARMV8_PMCR_X (1 << 4) /* Export to ETM */ +#define ARMV8_PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ +#define ARMV8_PMCR_N_SHIFT 11 /* Number of counters supported */ +#define ARMV8_PMCR_N_MASK 0x1f + +#define ARMV8_PMUSERENR_EN_EL0 (1 << 0) /* EL0 access enable */ +#define ARMV8_PMUSERENR_CR (1 << 2) /* Cycle counter read enable */ +#define ARMV8_PMUSERENR_ER (1 << 3) /* Event counter read enable */ +#define ARMV8_PMCNTENSET_EL0_ENABLE (1<<31) /**< Enable Perf count reg */ + +static inline void +on_each_cpu(void callback(void *data), void *data, int wait) +{ + + smp_rendezvous(NULL, callback, NULL, data); +} + + +static inline uint32_t armv8pmu_pmcr_read(void) +{ + uint64_t val=0; + __asm __volatile("mrs %0, pmcr_el0" : "=r" (val)); + return (uint32_t)val; +} + +static inline void armv8pmu_pmcr_write(uint32_t val) +{ + val &= ARMV8_PMCR_MASK; + isb(); + __asm __volatile("msr pmcr_el0, %0" : : "r" ((uint64_t)val)); +} + +static void +enable_cpu_counters(void* data) +{ + printf("PMU Counter User Access enabled\n"); + + /* Enable EL0 access to PMU counters */ + __asm __volatile("msr pmuserenr_el0, %0" : : "r" + ((uint64_t)ARMV8_PMUSERENR_EN_EL0|ARMV8_PMUSERENR_ER|ARMV8_PMUSERENR_CR)); + + /* Initialize and reset */ + armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C); + + /* Disable interrupt for counter overflow */ + __asm __volatile("msr pmintenset_el1, %0" : : "r" ((uint64_t)(0 << 31))); + + /* Enable Cycle counter register */ + __asm __volatile("msr pmcntenset_el0, %0" : : "r" + ((uint64_t)ARMV8_PMCNTENSET_EL0_ENABLE)); + + /*start*/ + armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E); +} + +static void +disable_cpu_counters(void* data) +{ + armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E); + + __asm __volatile("msr pmuserenr_el0, %0" : : "r"((uint64_t)0)); + +} + +static void enable_per_cpu_pmu(void) +{ + return on_each_cpu(enable_cpu_counters, NULL, 1); +} + +static void disable_per_cpu_pmu(void) +{ + return on_each_cpu(disable_cpu_counters, NULL, 1); +} + +SYSINIT(enable_per_cpu_pmu, SI_SUB_DRIVERS, SI_ORDER_ANY, + enable_per_cpu_pmu, NULL); +SYSUNINIT(disable_per_cpu_pmu, SI_SUB_DRIVERS, SI_ORDER_ANY, + disable_per_cpu_pmu, NULL); Index: sys/conf/files.arm64 =================================================================== --- sys/conf/files.arm64 +++ sys/conf/files.arm64 @@ -130,6 +130,7 @@ arm64/arm64/bus_machdep.c standard arm64/arm64/bus_space_asm.S standard arm64/arm64/busdma_bounce.c standard +arm64/arm64/pmu_enable.c optional pmu_cntr arm64/arm64/busdma_machdep.c standard arm64/arm64/bzero.S standard arm64/arm64/clock.c standard