]> Zhao Yanbai Git Server - minix.git/commitdiff
ARM: make cycle counter available to userspace
authorThomas Veerman <thomas@minix3.org>
Tue, 8 Jan 2013 10:53:08 +0000 (11:53 +0100)
committerThomas Veerman <thomas@minix3.org>
Fri, 11 Jan 2013 09:18:36 +0000 (09:18 +0000)
kernel/arch/arm/arch_system.c
kernel/arch/arm/omap_ccnt.h [new file with mode: 0644]
kernel/arch/arm/omap_timer.c
lib/libminlib/Makefile
lib/libminlib/arm/Makefile.inc
lib/libminlib/arm/read_tsc.c [new file with mode: 0644]
lib/libminlib/i386/Makefile.inc
lib/libminlib/read_tsc_64.c [moved from lib/libminlib/i386/read_tsc_64.c with 100% similarity]

index 8852cd1235fc261827bd1fa10d6f3ba9387adacd..c8af6cc09157a9ef881ba30edaade0a1e1643d8e 100644 (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));
 }
 
 /*===========================================================================*
diff --git a/kernel/arch/arm/omap_ccnt.h b/kernel/arch/arm/omap_ccnt.h
new file mode 100644 (file)
index 0000000..c4a3c78
--- /dev/null
@@ -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 */
index 20ac461108fc50c38a10b1cc2d7afc3ba7eee792..4821d2a19d8f38540af8574560eaaa882533bb96 100644 (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;
index ff6425dcbf9501f72044f3da9e215edb52290e9b..af025661c844556689e906d8e7d16f24eaff1de8 100644 (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
index 6c516659d3181201b9625774420e491a76c41508..e9852c42b08dbb9f6e07aa6da66bd7226adc1479 100644 (file)
@@ -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 (file)
index 0000000..2252615
--- /dev/null
@@ -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;
+}
+
index 9c252f948e3cfc545afe109c28ccb132974a0db4..34e821681c290d2c9c07bdf33bbb8588a767ea3c 100644 (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