diff options
author | bz <bz@FreeBSD.org> | 2015-11-09 17:57:32 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2015-11-09 17:57:32 +0000 |
commit | 200e80141f6254314818e969ed424fbe74842aa0 (patch) | |
tree | ab632b74c669ec0e2bedd87a573f8a0da5986cf0 | |
parent | 81ddf1e4ee32e244d8252d9aee03ef29b875b28e (diff) | |
download | FreeBSD-src-200e80141f6254314818e969ed424fbe74842aa0.zip FreeBSD-src-200e80141f6254314818e969ed424fbe74842aa0.tar.gz |
Now that the PMU implementation is independent of HWPMC
as of r288992 use it to manage the CCNT.
Use the CNNT for get_cyclecount() instead of binuptime() when device pmu
is compiled in; if it fails to attach, fall back to the former method.
Enable by default for the BeagleBoneBlack configuration.
Optained from: Cambridge/L41
Sponsored by: DARPA/AFRL
Reviewed by: andrew
Differential Revision: https://reviews.freebsd.org/D3837
-rw-r--r-- | sys/arm/arm/pmu.c | 51 | ||||
-rw-r--r-- | sys/arm/conf/BEAGLEBONE | 3 | ||||
-rw-r--r-- | sys/arm/include/cpu.h | 34 | ||||
-rw-r--r-- | sys/conf/options.arm | 1 |
4 files changed, 84 insertions, 5 deletions
diff --git a/sys/arm/arm/pmu.c b/sys/arm/arm/pmu.c index 1b079c0..4c39f60 100644 --- a/sys/arm/arm/pmu.c +++ b/sys/arm/arm/pmu.c @@ -94,16 +94,44 @@ static struct resource_spec pmu_spec[] = { { -1, 0 } }; +/* CCNT */ +#if __ARM_ARCH > 6 +int pmu_attched = 0; +uint32_t ccnt_hi[MAXCPU]; +#endif + +#define PMU_OVSR_C 0x80000000 /* Cycle Counter */ +#define PMU_IESR_C 0x80000000 /* Cycle Counter */ + static int pmu_intr(void *arg) { +#ifdef HWPMC_HOOKS struct trapframe *tf; - - tf = arg; +#endif + uint32_t r; +#if defined(__arm__) && (__ARM_ARCH > 6) + u_int cpu; + + cpu = PCPU_GET(cpuid); + + r = cp15_pmovsr_get(); + if (r & PMU_OVSR_C) { + atomic_add_32(&ccnt_hi[cpu], 1); + /* Clear the event. */ + r &= ~PMU_OVSR_C; + cp15_pmovsr_set(PMU_OVSR_C); + } +#else + r = 1; +#endif #ifdef HWPMC_HOOKS - if (pmc_intr) + /* Only call into the HWPMC framework if we know there is work. */ + if (r != 0 && pmc_intr) { + tf = arg; (*pmc_intr)(PCPU_GET(cpuid), tf); + } #endif return (FILTER_HANDLED); @@ -128,6 +156,9 @@ static int pmu_attach(device_t dev) { struct pmu_softc *sc; +#if defined(__arm__) && (__ARM_ARCH > 6) + uint32_t iesr; +#endif int err; int i; @@ -152,6 +183,20 @@ pmu_attach(device_t dev) } } +#if defined(__arm__) && (__ARM_ARCH > 6) + /* Initialize to 0. */ + for (i = 0; i < MAXCPU; i++) + ccnt_hi[i] = 0; + + /* Enable the interrupt to fire on overflow. */ + iesr = cp15_pminten_get(); + iesr |= PMU_IESR_C; + cp15_pminten_set(iesr); + + /* Need this for getcyclecount() fast path. */ + pmu_attched |= 1; +#endif + return (0); } diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE index 59c7279..3950e17 100644 --- a/sys/arm/conf/BEAGLEBONE +++ b/sys/arm/conf/BEAGLEBONE @@ -102,6 +102,9 @@ device ti_pruss # Mailbox support device ti_mbox +# PMU support (for CCNT). +device pmu + # USB support device usb options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h index 3411f32..782471e 100644 --- a/sys/arm/include/cpu.h +++ b/sys/arm/include/cpu.h @@ -14,12 +14,42 @@ void swi_vm(void *); #ifdef _KERNEL #if __ARM_ARCH >= 6 #include <machine/cpu-v6.h> -#endif +#ifdef DEV_PMU +#include <sys/pcpu.h> +#define PMU_OVSR_C 0x80000000 /* Cycle Counter */ +extern uint32_t ccnt_hi[MAXCPU]; +extern int pmu_attched; +#endif /* DEV_PMU */ +#endif /* __ARM_ARCH >= 6 */ + static __inline uint64_t get_cyclecount(void) { #if __ARM_ARCH >= 6 - return cp15_pmccntr_get(); +#if (__ARM_ARCH > 6) && defined(DEV_PMU) + if (pmu_attched) { + u_int cpu; + uint64_t h, h2; + uint32_t l, r; + + cpu = PCPU_GET(cpuid); + h = (uint64_t)atomic_load_acq_32(&ccnt_hi[cpu]); + l = cp15_pmccntr_get(); + /* In case interrupts are disabled we need to check for overflow. */ + r = cp15_pmovsr_get(); + if (r & PMU_OVSR_C) { + atomic_add_32(&ccnt_hi[cpu], 1); + /* Clear the event. */ + cp15_pmovsr_set(PMU_OVSR_C); + } + /* Make sure there was no wrap-around while we read the lo half. */ + h2 = (uint64_t)atomic_load_acq_32(&ccnt_hi[cpu]); + if (h != h2) + l = cp15_pmccntr_get(); + return (h2 << 32 | l); + } else +#endif + return cp15_pmccntr_get(); #else /* No performance counters, so use binuptime(9). This is slooooow */ struct bintime bt; diff --git a/sys/conf/options.arm b/sys/conf/options.arm index ada1174..a6dcae3 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -23,6 +23,7 @@ CPU_XSCALE_IXP425 opt_global.h CPU_XSCALE_IXP435 opt_global.h CPU_XSCALE_PXA2X0 opt_global.h DEV_GIC opt_global.h +DEV_PMU opt_global.h EFI opt_platform.h FLASHADDR opt_global.h GIC_DEFAULT_ICFGR_INIT opt_global.h |