From aa3623d873313f7029eb13ee5fbbd5c05191a8b8 Mon Sep 17 00:00:00 2001 From: Thomas Veerman Date: Tue, 8 Jan 2013 11:53:08 +0100 Subject: [PATCH] ARM: make cycle counter available to userspace --- kernel/arch/arm/arch_system.c | 18 ++++++++++++++++++ kernel/arch/arm/omap_ccnt.h | 21 +++++++++++++++++++++ kernel/arch/arm/omap_timer.c | 6 +++++- lib/libminlib/Makefile | 2 +- lib/libminlib/arm/Makefile.inc | 2 +- lib/libminlib/arm/read_tsc.c | 20 ++++++++++++++++++++ lib/libminlib/i386/Makefile.inc | 2 +- lib/libminlib/{i386 => }/read_tsc_64.c | 0 8 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 kernel/arch/arm/omap_ccnt.h create mode 100644 lib/libminlib/arm/read_tsc.c rename lib/libminlib/{i386 => }/read_tsc_64.c (100%) diff --git a/kernel/arch/arm/arch_system.c b/kernel/arch/arm/arch_system.c index 8852cd123..c8af6cc09 100644 --- a/kernel/arch/arm/arch_system.c +++ b/kernel/arch/arm/arch_system.c @@ -17,6 +17,7 @@ #include "serial.h" #include "kernel/proc.h" #include "kernel/debug.h" +#include "omap_ccnt.h" #include "glo.h" @@ -80,6 +81,8 @@ void cpu_identify(void) void arch_init(void) { + u32_t value; + k_stacks = (void*) &k_stacks_start; assert(!((vir_bytes) k_stacks % K_STACK_SIZE)); @@ -92,6 +95,21 @@ void arch_init(void) #endif ser_init(); + + /* enable user space access to cycle counter */ + /* set cycle counter to 0: ARM ARM B4.1.113 and B4.1.117 */ + asm volatile ("MRC p15, 0, %0, c9, c12, 0\t\n": "=r" (value)); + value |= OMAP_PMCR_C; /* Reset counter */ + value |= OMAP_PMCR_E; /* Enable counter hardware */ + asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n": : "r" (value)); + + /* enable CCNT counting: ARM ARM B4.1.116 */ + value = OMAP_PMCNTENSET_C; /* Enable PMCCNTR cycle counter */ + asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n": : "r" (value)); + + /* enable cycle counter in user mode: ARM ARM B4.1.124 */ + value = OMAP_PMUSERENR_EN; + asm volatile ("MCR p15, 0, %0, c9, c14, 0\t\n": : "r" (value)); } /*===========================================================================* diff --git a/kernel/arch/arm/omap_ccnt.h b/kernel/arch/arm/omap_ccnt.h new file mode 100644 index 000000000..c4a3c7823 --- /dev/null +++ b/kernel/arch/arm/omap_ccnt.h @@ -0,0 +1,21 @@ +#ifndef _OMAP_CCNT_H +#define _OMAP_CCNT_H + +/* ARM ARM B4.1.116 */ +#define OMAP_PMCNTENSET_C (1 << 31) /* Enable PMCCNTR cycle counter */ + +/* ARM ARM B4.1.117 PMCR */ +#define OMAP_PMCR_DP (1 << 5) /* Disable when ev. cnt. prohibited */ +#define OMAP_PMCR_X (1 << 4) /* Export enable */ +#define OMAP_PMCR_D (1 << 3) /* Clock divider */ +#define OMAP_PMCR_C (1 << 2) /* Cycle counter reset */ +#define OMAP_PMCR_P (1 << 1) /* Event counter reset */ +#define OMAP_PMCR_E (1 << 0) /* Enable event counters */ + +/* ARM ARM B4.1.119 PMINTENSET */ +#define OMAP_PMINTENSET_C (1 << 31) /* PMCCNTR overflow int req. enable*/ + +/* ARM ARM B4.1.124 PMUSERENR */ +#define OMAP_PMUSERENR_EN (1 << 0) /* User mode access enable bit */ + +#endif /* _OMAP_CCNT_H */ diff --git a/kernel/arch/arm/omap_timer.c b/kernel/arch/arm/omap_timer.c index 20ac46110..4821d2a19 100644 --- a/kernel/arch/arm/omap_timer.c +++ b/kernel/arch/arm/omap_timer.c @@ -8,6 +8,7 @@ #include "omap_intr.h" static irq_hook_t omap3_timer_hook; /* interrupt handler hook */ +static u64_t tsc; int omap3_register_timer_handler(const irq_handler_t handler) { @@ -52,7 +53,6 @@ void omap3_timer_stop() mmio_clear(OMAP3_GPTIMER1_TCLR, OMAP3_TCLR_ST); } -static u64_t tsc; void omap3_timer_int_handler() { /* Clear the interrupt */ @@ -60,6 +60,10 @@ void omap3_timer_int_handler() tsc++; } +/* Don't use libminlib's read_tsc_64, but our own version instead. We emulate + * the ARM Cycle Counter (CCNT) with 1 cycle per ms. We can't rely on the + * actual counter hardware to be working (i.e., qemu doesn't emulate it at all) + */ void read_tsc_64(u64_t *t) { *t = tsc; diff --git a/lib/libminlib/Makefile b/lib/libminlib/Makefile index ff6425dcb..af025661c 100644 --- a/lib/libminlib/Makefile +++ b/lib/libminlib/Makefile @@ -19,7 +19,7 @@ SRCS+= dhcp_gettag.c dhcp_settag.c SRCS+= gcov.c gcov_flush.c # Various utils -SRCS+= itoa.c u64util.c +SRCS+= itoa.c u64util.c read_tsc_64.c # svrctl SRCS+= svrctl.c diff --git a/lib/libminlib/arm/Makefile.inc b/lib/libminlib/arm/Makefile.inc index 6c516659d..e9852c42b 100644 --- a/lib/libminlib/arm/Makefile.inc +++ b/lib/libminlib/arm/Makefile.inc @@ -1 +1 @@ -SRCS+= get_bp.S +SRCS+= get_bp.S read_tsc.c diff --git a/lib/libminlib/arm/read_tsc.c b/lib/libminlib/arm/read_tsc.c new file mode 100644 index 000000000..2252615dd --- /dev/null +++ b/lib/libminlib/arm/read_tsc.c @@ -0,0 +1,20 @@ +#include + +void +read_tsc(u32_t *hi, u32_t *lo) +{ +/* Read Clock Cycle Counter (CCNT). Intel calls it Time Stamp Counter (TSC) */ + u32_t ccnt; + + /* Get value from the Performance Monitors Cycle Counter Register. + * See ARM Architecture Reference Manual B5.1.113. + */ + asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n" : "=r" (ccnt) : : "%0"); + + /* The ARMv7-A clock cycle counter is only 32-bits, but read_tsc is + * expected to return a 64-bit value. hi is therefore always 0. + */ + *hi = 0; + *lo = ccnt; +} + diff --git a/lib/libminlib/i386/Makefile.inc b/lib/libminlib/i386/Makefile.inc index 9c252f948..34e821681 100644 --- a/lib/libminlib/i386/Makefile.inc +++ b/lib/libminlib/i386/Makefile.inc @@ -1,2 +1,2 @@ SRCS+= _cpufeature.c _cpuid.S get_bp.S getprocessor.S \ - read_tsc.S read_tsc_64.c + read_tsc.S diff --git a/lib/libminlib/i386/read_tsc_64.c b/lib/libminlib/read_tsc_64.c similarity index 100% rename from lib/libminlib/i386/read_tsc_64.c rename to lib/libminlib/read_tsc_64.c -- 2.44.0