Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Nov 2015 17:57:32 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r290614 - in head/sys: arm/arm arm/conf arm/include conf
Message-ID:  <201511091757.tA9HvWCk081852@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511091757.tA9HvWCk081852>