ARM: make cycle counter available to userspace

This commit is contained in:
Thomas Veerman 2013-01-08 11:53:08 +01:00
parent ea8ff9284a
commit aa3623d873
8 changed files with 67 additions and 4 deletions

View file

@ -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));
}
/*===========================================================================*

View file

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

View file

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

View file

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

View file

@ -1 +1 @@
SRCS+= get_bp.S
SRCS+= get_bp.S read_tsc.c

View file

@ -0,0 +1,20 @@
#include <sys/types.h>
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;
}

View file

@ -1,2 +1,2 @@
SRCS+= _cpufeature.c _cpuid.S get_bp.S getprocessor.S \
read_tsc.S read_tsc_64.c
read_tsc.S