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:
parent
3b383c9ede
commit
eeaf6acbfd
@ -94,16 +94,44 @@ static struct resource_spec pmu_spec[] = {
|
|||||||
{ -1, 0 }
|
{ -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
|
static int
|
||||||
pmu_intr(void *arg)
|
pmu_intr(void *arg)
|
||||||
{
|
{
|
||||||
|
#ifdef HWPMC_HOOKS
|
||||||
struct trapframe *tf;
|
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
|
#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);
|
(*pmc_intr)(PCPU_GET(cpuid), tf);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (FILTER_HANDLED);
|
return (FILTER_HANDLED);
|
||||||
@ -128,6 +156,9 @@ static int
|
|||||||
pmu_attach(device_t dev)
|
pmu_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct pmu_softc *sc;
|
struct pmu_softc *sc;
|
||||||
|
#if defined(__arm__) && (__ARM_ARCH > 6)
|
||||||
|
uint32_t iesr;
|
||||||
|
#endif
|
||||||
int err;
|
int err;
|
||||||
int i;
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,9 @@ device ti_pruss
|
|||||||
# Mailbox support
|
# Mailbox support
|
||||||
device ti_mbox
|
device ti_mbox
|
||||||
|
|
||||||
|
# PMU support (for CCNT).
|
||||||
|
device pmu
|
||||||
|
|
||||||
# USB support
|
# USB support
|
||||||
device usb
|
device usb
|
||||||
options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
|
options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
|
||||||
|
@ -14,11 +14,41 @@ void swi_vm(void *);
|
|||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
#if __ARM_ARCH >= 6
|
#if __ARM_ARCH >= 6
|
||||||
#include <machine/cpu-v6.h>
|
#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
|
static __inline uint64_t
|
||||||
get_cyclecount(void)
|
get_cyclecount(void)
|
||||||
{
|
{
|
||||||
#if __ARM_ARCH >= 6
|
#if __ARM_ARCH >= 6
|
||||||
|
#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();
|
return cp15_pmccntr_get();
|
||||||
#else /* No performance counters, so use binuptime(9). This is slooooow */
|
#else /* No performance counters, so use binuptime(9). This is slooooow */
|
||||||
struct bintime bt;
|
struct bintime bt;
|
||||||
|
@ -23,6 +23,7 @@ CPU_XSCALE_IXP425 opt_global.h
|
|||||||
CPU_XSCALE_IXP435 opt_global.h
|
CPU_XSCALE_IXP435 opt_global.h
|
||||||
CPU_XSCALE_PXA2X0 opt_global.h
|
CPU_XSCALE_PXA2X0 opt_global.h
|
||||||
DEV_GIC opt_global.h
|
DEV_GIC opt_global.h
|
||||||
|
DEV_PMU opt_global.h
|
||||||
EFI opt_platform.h
|
EFI opt_platform.h
|
||||||
FLASHADDR opt_global.h
|
FLASHADDR opt_global.h
|
||||||
GIC_DEFAULT_ICFGR_INIT opt_global.h
|
GIC_DEFAULT_ICFGR_INIT opt_global.h
|
||||||
|
Loading…
x
Reference in New Issue
Block a user