summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/man/2/cputime1
-rw-r--r--sys/src/9/bcm64/clock.c19
-rw-r--r--sys/src/9/bcm64/sysreg.h2
-rw-r--r--sys/src/libc/arm64/cycles.s4
4 files changed, 21 insertions, 5 deletions
diff --git a/sys/man/2/cputime b/sys/man/2/cputime
index 4d6440116..282e93ade 100644
--- a/sys/man/2/cputime
+++ b/sys/man/2/cputime
@@ -39,6 +39,7 @@ if any, and stores it via
Currently supported architectures are
.BR 386 ,
.BR amd64 ,
+.B arm64
and
.BR power ;
on all others,
diff --git a/sys/src/9/bcm64/clock.c b/sys/src/9/bcm64/clock.c
index f7b3e55f7..f5fcc4784 100644
--- a/sys/src/9/bcm64/clock.c
+++ b/sys/src/9/bcm64/clock.c
@@ -2,14 +2,14 @@
* bcm283[56] timers
* System timers run at 1MHz (timers 1 and 2 are used by GPU)
* ARM timer usually runs at 250MHz (may be slower in low power modes)
- * Cycle counter runs at 700MHz (unless overclocked)
* All are free-running up-counters
*
* Use system timer 3 (64 bits) for hzclock interrupts and fastticks
* For smp on bcm2836, use local generic timer for interrupts on cpu1-3
* Use ARM timer (32 bits) for perfticks
* Use ARM timer to force immediate interrupt
- * Use cycle counter for cycles()
+ * Use performance cycle counter for lcycles()
+ * Use generic timer virtual counter for cycles()
*/
#include "u.h"
@@ -118,6 +118,7 @@ clockinit(void)
syswr(PMCR_EL0, 1<<6 | 7);
syswr(PMCNTENSET, 1<<31);
syswr(PMUSERENR_EL0, 1<<2);
+ syswr(CNTKCTL_EL1, 1<<1);
syswr(CNTP_TVAL_EL0, ~0UL);
if(m->machno == 0){
@@ -147,7 +148,19 @@ clockinit(void)
t1 -= t0;
m->cpuhz = 100 * t1;
m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz;
- m->cyclefreq = m->cpuhz;
+
+ /*
+ * Cyclefreq used to be the same as cpuhz as
+ * we where using the PMCCNTR_EL0 which counts
+ * per core cpu cycles. But is is kind of useless
+ * in userspace because each core has a differnet
+ * counter and it stops when the core is idle (WFI).
+ * So we change it to use the generic timer
+ * virtual counter register CNTVCT_EL0 instead
+ * running at the same frequency as system timer.
+ * (CNTFRQ_EL0 is WRONG on raspberry pi).
+ */
+ m->cyclefreq = SystimerFreq;
if(m->machno == 0){
tn->cs = 1<<3;
diff --git a/sys/src/9/bcm64/sysreg.h b/sys/src/9/bcm64/sysreg.h
index c057bbba8..0d9b1b172 100644
--- a/sys/src/9/bcm64/sysreg.h
+++ b/sys/src/9/bcm64/sysreg.h
@@ -32,6 +32,8 @@
#define PMUSERENR_EL0 SYSREG(3,3,9,14,0)
#define CNTPCT_EL0 SYSREG(3,3,14,0,1)
+#define CNTVCT_EL0 SYSREG(3,3,14,0,2)
+#define CNTKCTL_EL1 SYSREG(3,0,14,1,0)
#define CNTP_TVAL_EL0 SYSREG(3,3,14,2,0)
#define CNTP_CTL_EL0 SYSREG(3,3,14,2,1)
#define CNTP_CVAL_EL0 SYSREG(3,3,14,2,2)
diff --git a/sys/src/libc/arm64/cycles.s b/sys/src/libc/arm64/cycles.s
index 389ea201f..03955b9ad 100644
--- a/sys/src/libc/arm64/cycles.s
+++ b/sys/src/libc/arm64/cycles.s
@@ -1,7 +1,7 @@
#define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5))
-#define PMCCNTR_EL0 SYSREG(3,3,9,13,0)
+#define CNTVCT_EL0 SYSREG(3,3,14,0,2)
TEXT cycles(SB), 1, $-4
- MRS PMCCNTR_EL0, R1
+ MRS CNTVCT_EL0, R1
MOV R1, (R0)
RETURN