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
This commit is contained in:
Bjoern A. Zeeb 2015-11-09 17:57:32 +00:00
parent 3b383c9ede
commit eeaf6acbfd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=290614
4 changed files with 83 additions and 4 deletions

View File

@ -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;
#endif
uint32_t r;
#if defined(__arm__) && (__ARM_ARCH > 6)
u_int cpu;
tf = arg;
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);
}

View File

@ -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.

View File

@ -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;

View File

@ -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