Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-7]: src/sys/arch/arm/cortex Pull up following revision(s) (reques...



details:   https://anonhg.NetBSD.org/src/rev/c15613fd22b7
branches:  netbsd-7
changeset: 799173:c15613fd22b7
user:      snj <snj%NetBSD.org@localhost>
date:      Mon Apr 06 01:55:53 2015 +0000

description:
Pull up following revision(s) (requested by skrll in ticket #662):
        sys/arch/arm/cortex/gtmr.c: revision 1.10-1.14
port-arm/49737: armgtmr0 timer broken
Use physical timer instead of virtual timer for timecounter. For platforms
that implement virtualization extensions, the CNTVOFF register defines a
virtual offset between the physical count and virtual count. Unfortunately,
the CNTVOFF register is only accessible in secure mode and the value is
per-CPU, so we may end up in a scenario where virtual count reads from
CPU A -> B -> A are not monotonic. No offset applied to physical timer,
so physical count reads are guaranteed to be monotonic.
--
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.)
--
Move isb's to before reading count.  Change interrupt to level.
--
Trailing whitespace.
--
Whitespace

diffstat:

 sys/arch/arm/cortex/gtmr.c |  40 ++++++++++++++++++++++++++--------------
 1 files changed, 26 insertions(+), 14 deletions(-)

diffs (157 lines):

diff -r f063df71a656 -r c15613fd22b7 sys/arch/arm/cortex/gtmr.c
--- a/sys/arch/arm/cortex/gtmr.c        Mon Apr 06 01:48:25 2015 +0000
+++ b/sys/arch/arm/cortex/gtmr.c        Mon Apr 06 01:55:53 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gtmr.c,v 1.8.2.1 2015/03/11 20:22:55 snj Exp $ */
+/*     $NetBSD: gtmr.c,v 1.8.2.2 2015/04/06 01:55:53 snj Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.8.2.1 2015/03/11 20:22:55 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.8.2.2 2015/04/06 01:55:53 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -44,6 +44,8 @@
 
 #include <prop/proplib.h>
 
+#include <arm/locore.h>
+
 #include <arm/cortex/gtmr_var.h>
 
 #include <arm/cortex/mpcore_var.h>
@@ -94,14 +96,14 @@
 gtmr_attach(device_t parent, device_t self, void *aux)
 {
        struct mpcore_attach_args * const mpcaa = aux;
-        struct gtmr_softc *sc = &gtmr_sc;
+       struct gtmr_softc *sc = &gtmr_sc;
        prop_dictionary_t dict = device_properties(self);
        char freqbuf[sizeof("X.XXX SHz")];
 
        /*
         * This runs at a fixed frequency of 1 to 50MHz.
         */
-       prop_dictionary_get_uint32(dict, "frequency", &sc->sc_freq);            
+       prop_dictionary_get_uint32(dict, "frequency", &sc->sc_freq);
        KASSERT(sc->sc_freq != 0);
 
        humanize_number(freqbuf, sizeof(freqbuf), sc->sc_freq, "Hz", 1000);
@@ -112,7 +114,8 @@
        /*
         * Enable the virtual counter to be accessed from usermode.
         */
-       armreg_cntk_ctl_write(armreg_cntk_ctl_read() | ARM_CNTKCTL_PL0VCTEN);
+       armreg_cntk_ctl_write(armreg_cntk_ctl_read() |
+           ARM_CNTKCTL_PL0VCTEN | ARM_CNTKCTL_PL0PCTEN);
 
        self->dv_private = sc;
        sc->sc_dev = self;
@@ -125,7 +128,7 @@
            device_xname(self), "missing interrupts");
 
        sc->sc_global_ih = intr_establish(mpcaa->mpcaa_irq, IPL_CLOCK,
-           IST_EDGE | IST_MPSAFE, gtmr_intr, NULL);
+           IST_LEVEL | IST_MPSAFE, gtmr_intr, NULL);
        if (sc->sc_global_ih == NULL)
                panic("%s: unable to register timer interrupt", __func__);
        aprint_normal_dev(self, "interrupting on irq %d\n",
@@ -159,6 +162,7 @@
         * enable timer and stop masking the timer.
         */
        armreg_cntv_ctl_write(ARM_CNTCTL_ENABLE);
+       armreg_cntp_ctl_write(ARM_CNTCTL_ENABLE);
 #if 0
        printf("%s: cntctl=%#x\n", __func__, armreg_cntv_ctl_read());
 #endif
@@ -166,6 +170,7 @@
        /*
         * Get now and update the compare timer.
         */
+       arm_isb();
        ci->ci_lastintr = armreg_cntv_ct_read();
        armreg_cntv_tval_write(sc->sc_autoinc);
 #if 0
@@ -182,21 +187,24 @@
 
        s = splsched();
 
+       arm_isb();
        uint64_t now64;
        uint64_t start64 = armreg_cntv_ct_read();
        do {
+               arm_isb();
                now64 = armreg_cntv_ct_read();
        } while (start64 == now64);
        start64 = now64;
        uint64_t end64 = start64 + 64;
        uint32_t start32 = armreg_pmccntr_read();
        do {
+               arm_isb();
                now64 = armreg_cntv_ct_read();
        } while (end64 != now64);
        uint32_t end32 = armreg_pmccntr_read();
 
        uint32_t diff32 = end64 - start64;
-       printf("%s: %s: %u cycles per tick\n", 
+       printf("%s: %s: %u cycles per tick\n",
            __func__, ci->ci_data.cpu_name, (end32 - start32) / diff32);
 
        printf("%s: %s: status %#x cmp %#"PRIx64" now %#"PRIx64"\n",
@@ -204,7 +212,7 @@
            armreg_cntv_cval_read(), armreg_cntv_ct_read());
        splx(s);
 #elif 0
-       delay(1000000 / hz + 1000); 
+       delay(1000000 / hz + 1000);
 #endif
 }
 
@@ -237,12 +245,13 @@
         */
        const uint64_t incr_per_us = (freq >> 20) + (freq >> 24);
 
+       arm_isb();
+       const uint64_t base = armreg_cntv_ct_read();
        const uint64_t delta = n * incr_per_us;
-       const uint64_t base = armreg_cntv_ct_read();
        const uint64_t finish = base + delta;
 
        while (armreg_cntv_ct_read() < finish) {
-               /* spin */
+               arm_isb();      /* spin */
        }
 }
 
@@ -271,12 +280,15 @@
 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 = &gtmr_sc;
 
+       arm_isb();
+
+       const uint64_t now = armreg_cntv_ct_read();
+       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);
@@ -327,6 +339,6 @@
 static u_int
 gtmr_get_timecount(struct timecounter *tc)
 {
-
-       return (u_int) (armreg_cntv_ct_read());
+       arm_isb();      // we want the time NOW, not some instructions later.
+       return (u_int) armreg_cntp_ct_read();
 }



Home | Main Index | Thread Index | Old Index