svn commit: r290614 - in head/sys: arm/arm arm/conf arm/include conf
Bjoern A. Zeeb
bz at FreeBSD.org
Mon Nov 9 17:57:33 UTC 2015
Author: bz
Date: Mon Nov 9 17:57:32 2015
New Revision: 290614
URL: https://svnweb.freebsd.org/changeset/base/290614
Log:
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
Modified:
head/sys/arm/arm/pmu.c
head/sys/arm/conf/BEAGLEBONE
head/sys/arm/include/cpu.h
head/sys/conf/options.arm
Modified: head/sys/arm/arm/pmu.c
==============================================================================
--- head/sys/arm/arm/pmu.c Mon Nov 9 16:50:42 2015 (r290613)
+++ head/sys/arm/arm/pmu.c Mon Nov 9 17:57:32 2015 (r290614)
@@ -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);
}
Modified: head/sys/arm/conf/BEAGLEBONE
==============================================================================
--- head/sys/arm/conf/BEAGLEBONE Mon Nov 9 16:50:42 2015 (r290613)
+++ head/sys/arm/conf/BEAGLEBONE Mon Nov 9 17:57:32 2015 (r290614)
@@ -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.
Modified: head/sys/arm/include/cpu.h
==============================================================================
--- head/sys/arm/include/cpu.h Mon Nov 9 16:50:42 2015 (r290613)
+++ head/sys/arm/include/cpu.h Mon Nov 9 17:57:32 2015 (r290614)
@@ -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;
Modified: head/sys/conf/options.arm
==============================================================================
--- head/sys/conf/options.arm Mon Nov 9 16:50:42 2015 (r290613)
+++ head/sys/conf/options.arm Mon Nov 9 17:57:32 2015 (r290614)
@@ -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
More information about the svn-src-all
mailing list