summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2015-11-09 17:57:32 +0000
committerbz <bz@FreeBSD.org>2015-11-09 17:57:32 +0000
commit200e80141f6254314818e969ed424fbe74842aa0 (patch)
treeab632b74c669ec0e2bedd87a573f8a0da5986cf0
parent81ddf1e4ee32e244d8252d9aee03ef29b875b28e (diff)
downloadFreeBSD-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.c51
-rw-r--r--sys/arm/conf/BEAGLEBONE3
-rw-r--r--sys/arm/include/cpu.h34
-rw-r--r--sys/conf/options.arm1
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
OpenPOWER on IntegriCloud