Module Name: src Committed By: matt Date: Tue Mar 24 08:58:41 UTC 2015
Modified Files: src/sys/arch/arm/cortex: gtmr.c Log Message: Sprinkle some arm_isb() to force execution of the mcrr instructions to get more accurate values. (Given that the generic timer is usually running at a 64th or less of the cpu clock, this only settle to a tick or so.) To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/cortex/gtmr.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/cortex/gtmr.c diff -u src/sys/arch/arm/cortex/gtmr.c:1.10 src/sys/arch/arm/cortex/gtmr.c:1.11 --- src/sys/arch/arm/cortex/gtmr.c:1.10 Mon Mar 23 23:33:22 2015 +++ src/sys/arch/arm/cortex/gtmr.c Tue Mar 24 08:58:41 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: gtmr.c,v 1.10 2015/03/23 23:33:22 jmcneill Exp $ */ +/* $NetBSD: gtmr.c,v 1.11 2015/03/24 08:58:41 matt Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.10 2015/03/23 23:33:22 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.11 2015/03/24 08:58:41 matt Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -44,6 +44,8 @@ __KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.1 #include <prop/proplib.h> +#include <arm/locore.h> + #include <arm/cortex/gtmr_var.h> #include <arm/cortex/mpcore_var.h> @@ -169,6 +171,7 @@ gtmr_init_cpu_clock(struct cpu_info *ci) * Get now and update the compare timer. */ ci->ci_lastintr = armreg_cntv_ct_read(); + arm_isb(); armreg_cntv_tval_write(sc->sc_autoinc); #if 0 printf("%s: %s: delta cval = %"PRIu64"\n", @@ -186,14 +189,17 @@ gtmr_init_cpu_clock(struct cpu_info *ci) uint64_t now64; uint64_t start64 = armreg_cntv_ct_read(); + arm_isb(); do { now64 = armreg_cntv_ct_read(); + arm_isb(); } while (start64 == now64); start64 = now64; uint64_t end64 = start64 + 64; uint32_t start32 = armreg_pmccntr_read(); do { now64 = armreg_cntv_ct_read(); + arm_isb(); } while (end64 != now64); uint32_t end32 = armreg_pmccntr_read(); @@ -241,10 +247,11 @@ gtmr_delay(unsigned int n) const uint64_t delta = n * incr_per_us; const uint64_t base = armreg_cntv_ct_read(); + arm_isb(); const uint64_t finish = base + delta; while (armreg_cntv_ct_read() < finish) { - /* spin */ + arm_isb(); /* spin */ } } @@ -273,12 +280,16 @@ gtmr_bootdelay(unsigned int ticks) int gtmr_intr(void *arg) { - const uint64_t now = armreg_cntv_ct_read(); struct cpu_info * const ci = curcpu(); - uint64_t delta = now - ci->ci_lastintr; struct clockframe * const cf = arg; struct gtmr_softc * const sc = >mr_sc; + const uint64_t now = armreg_cntv_ct_read(); + + arm_isb(); + + uint64_t delta = now - ci->ci_lastintr; + #ifdef DIAGNOSTIC const uint64_t then = armreg_cntv_cval_read(); struct gtmr_percpu * const pc = percpu_getref(sc->sc_percpu); @@ -329,6 +340,9 @@ setstatclockrate(int newhz) static u_int gtmr_get_timecount(struct timecounter *tc) { + u_int now = (u_int) armreg_cntp_ct_read(); + + arm_isb(); // we want the time NOW, not some instructions later. - return (u_int) (armreg_cntp_ct_read()); + return now; }