Module Name: src Committed By: martin Date: Tue Aug 13 14:57:50 UTC 2019
Modified Files: src/sys/arch/aarch64/include [netbsd-9]: armreg.h src/sys/arch/arm/cortex [netbsd-9]: gtmr.c gtmr_var.h src/sys/arch/arm/include [netbsd-9]: armreg.h Log Message: Pull up following revision(s) (requested by jmcneill in ticket #54): sys/arch/aarch64/include/armreg.h: revision 1.26 sys/arch/arm/cortex/gtmr.c: revision 1.41 sys/arch/arm/include/armreg.h: revision 1.128 sys/arch/arm/cortex/gtmr_var.h: revision 1.12 Add support for physical timers and sprinkle isb where needed. To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.25.2.1 src/sys/arch/aarch64/include/armreg.h cvs rdiff -u -r1.40 -r1.40.2.1 src/sys/arch/arm/cortex/gtmr.c cvs rdiff -u -r1.11 -r1.11.4.1 src/sys/arch/arm/cortex/gtmr_var.h cvs rdiff -u -r1.127 -r1.127.2.1 src/sys/arch/arm/include/armreg.h 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/aarch64/include/armreg.h diff -u src/sys/arch/aarch64/include/armreg.h:1.25 src/sys/arch/aarch64/include/armreg.h:1.25.2.1 --- src/sys/arch/aarch64/include/armreg.h:1.25 Sun Jun 16 15:16:15 2019 +++ src/sys/arch/aarch64/include/armreg.h Tue Aug 13 14:57:49 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: armreg.h,v 1.25 2019/06/16 15:16:15 skrll Exp $ */ +/* $NetBSD: armreg.h,v 1.25.2.1 2019/08/13 14:57:49 martin Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -1138,6 +1138,16 @@ gtmr_cntv_ctl_write(uint32_t val) reg_cntv_ctl_el0_write(val); } +/* + * Counter-timer Physical Timer Control register + */ +static __inline uint32_t +gtmr_cntp_ctl_read(void) +{ + + return reg_cntp_ctl_el0_read(); +} + static __inline void gtmr_cntp_ctl_write(uint32_t val) { @@ -1146,6 +1156,23 @@ gtmr_cntp_ctl_write(uint32_t val) } /* + * Counter-timer Physical Timer TimerValue register + */ +static __inline uint32_t +gtmr_cntp_tval_read(void) +{ + + return reg_cntp_tval_el0_read(); +} + +static __inline void +gtmr_cntp_tval_write(uint32_t val) +{ + + reg_cntp_tval_el0_write(val); +} + +/* * Counter-timer Virtual Timer TimerValue register */ static __inline uint32_t @@ -1162,6 +1189,22 @@ gtmr_cntv_tval_write(uint32_t val) reg_cntv_tval_el0_write(val); } +/* + * Counter-timer Physical Timer CompareValue register + */ +static __inline uint64_t +gtmr_cntp_cval_read(void) +{ + + return reg_cntp_cval_el0_read(); +} + +static __inline void +gtmr_cntp_cval_write(uint64_t val) +{ + + reg_cntp_cval_el0_write(val); +} /* * Counter-timer Virtual Timer CompareValue register Index: src/sys/arch/arm/cortex/gtmr.c diff -u src/sys/arch/arm/cortex/gtmr.c:1.40 src/sys/arch/arm/cortex/gtmr.c:1.40.2.1 --- src/sys/arch/arm/cortex/gtmr.c:1.40 Sun Jun 16 10:57:59 2019 +++ src/sys/arch/arm/cortex/gtmr.c Tue Aug 13 14:57:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: gtmr.c,v 1.40 2019/06/16 10:57:59 jmcneill Exp $ */ +/* $NetBSD: gtmr.c,v 1.40.2.1 2019/08/13 14:57:50 martin Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.40 2019/06/16 10:57:59 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gtmr.c,v 1.40.2.1 2019/08/13 14:57:50 martin Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -55,6 +55,12 @@ static void gtmr_attach(device_t, device static u_int gtmr_get_timecount(struct timecounter *); +static uint64_t gtmr_read_cntct(struct gtmr_softc *); +static uint32_t gtmr_read_ctl(struct gtmr_softc *); +static void gtmr_write_ctl(struct gtmr_softc *, uint32_t); +static void gtmr_write_tval(struct gtmr_softc *, uint32_t); +static void gtmr_write_cval(struct gtmr_softc *, uint64_t); + static struct gtmr_softc gtmr_sc; struct gtmr_percpu { @@ -99,6 +105,7 @@ gtmr_attach(device_t parent, device_t se struct mpcore_attach_args * const mpcaa = aux; struct gtmr_softc *sc = >mr_sc; prop_dictionary_t dict = device_properties(self); + prop_dictionary_t pdict = device_properties(device_parent(self)); char freqbuf[sizeof("X.XXX SHz")]; bool flag; @@ -108,12 +115,16 @@ gtmr_attach(device_t parent, device_t se if (!prop_dictionary_get_uint32(dict, "frequency", &sc->sc_freq)) sc->sc_freq = gtmr_cntfrq_read(); + if (!prop_dictionary_get_bool(dict, "physical", &sc->sc_physical)) + prop_dictionary_get_bool(pdict, "physical", &sc->sc_physical); + KASSERT(sc->sc_freq != 0); humanize_number(freqbuf, sizeof(freqbuf), sc->sc_freq, "Hz", 1000); aprint_naive("\n"); - aprint_normal(": ARM Generic Timer (%s)\n", freqbuf); + aprint_normal(": Generic Timer (%s, %s)\n", freqbuf, + sc->sc_physical ? "physical" : "virtual"); if (prop_dictionary_get_bool(dict, "sun50i-a64-unstable-timer", &flag) && flag) { sc->sc_flags |= GTMR_FLAG_SUN50I_A64_UNSTABLE_TIMER; @@ -155,12 +166,14 @@ gtmr_attach(device_t parent, device_t se tc_init(>mr_timecounter); /* Disable the timer until we are ready */ - gtmr_cntv_ctl_write(0); + gtmr_write_ctl(sc, 0); } static uint64_t -gtmr_read_cntvct(struct gtmr_softc *sc) +gtmr_read_cntct(struct gtmr_softc *sc) { + arm_isb(); + if (ISSET(sc->sc_flags, GTMR_FLAG_SUN50I_A64_UNSTABLE_TIMER)) { /* * The Allwinner A64 SoC has an unstable architectural timer. @@ -170,19 +183,63 @@ gtmr_read_cntvct(struct gtmr_softc *sc) uint64_t val; u_int bits; do { - val = gtmr_cntvct_read(); + val = sc->sc_physical ? gtmr_cntpct_read() : gtmr_cntvct_read(); bits = val & __BITS(9,0); } while (bits == 0 || bits == __BITS(9,0)); return val; } - return gtmr_cntvct_read(); + return sc->sc_physical ? gtmr_cntpct_read() : gtmr_cntvct_read(); +} + +static uint32_t +gtmr_read_ctl(struct gtmr_softc *sc) +{ + if (sc->sc_physical) + return gtmr_cntp_ctl_read(); + else + return gtmr_cntv_ctl_read(); +} + +static void +gtmr_write_ctl(struct gtmr_softc *sc, uint32_t val) +{ + if (sc->sc_physical) + gtmr_cntp_ctl_write(val); + else + gtmr_cntv_ctl_write(val); + + arm_isb(); +} + +static void +gtmr_write_tval(struct gtmr_softc *sc, uint32_t val) +{ + if (sc->sc_physical) + gtmr_cntp_tval_write(val); + else + gtmr_cntv_tval_write(val); + + arm_isb(); } +static void +gtmr_write_cval(struct gtmr_softc *sc, uint64_t val) +{ + if (sc->sc_physical) + gtmr_cntp_cval_write(val); + else + gtmr_cntv_cval_write(val); + + arm_isb(); +} + + void gtmr_init_cpu_clock(struct cpu_info *ci) { struct gtmr_softc * const sc = >mr_sc; + uint32_t val; KASSERT(ci == curcpu()); @@ -192,22 +249,30 @@ gtmr_init_cpu_clock(struct cpu_info *ci) * Allow the virtual and physical counters to be accessed from * usermode. (PL0) */ - gtmr_cntk_ctl_write(gtmr_cntk_ctl_read() | - CNTKCTL_PL0VCTEN | CNTKCTL_PL0PCTEN); + val = gtmr_cntk_ctl_read(); + val &= ~(CNTKCTL_PL0PTEN | CNTKCTL_PL0VTEN | CNTKCTL_EVNTEN); + if (sc->sc_physical) { + val |= CNTKCTL_PL0PCTEN; + val &= ~CNTKCTL_PL0VCTEN; + } else { + val |= CNTKCTL_PL0VCTEN; + val &= ~CNTKCTL_PL0PCTEN; + } + gtmr_cntk_ctl_write(val); + arm_isb(); /* * enable timer and stop masking the timer. */ - gtmr_cntv_ctl_write(CNTCTL_ENABLE); + gtmr_write_ctl(sc, CNTCTL_ENABLE); /* * Get now and update the compare timer. */ - arm_isb(); - ci->ci_lastintr = gtmr_read_cntvct(sc); - gtmr_cntv_tval_write(sc->sc_autoinc); + ci->ci_lastintr = gtmr_read_cntct(sc); + gtmr_write_tval(sc, sc->sc_autoinc); splx(s); - KASSERT(gtmr_read_cntvct(sc) != 0); + KASSERT(gtmr_read_cntct(sc) != 0); } void @@ -236,12 +301,10 @@ gtmr_delay(unsigned int n) const unsigned int incr_per_us = howmany(freq, 1000000); int64_t ticks = (int64_t)n * incr_per_us; - arm_isb(); - uint64_t last = gtmr_read_cntvct(sc); + uint64_t last = gtmr_read_cntct(sc); while (ticks > 0) { - arm_isb(); - uint64_t curr = gtmr_read_cntvct(sc); + uint64_t curr = gtmr_read_cntct(sc); if (curr >= last) ticks -= (curr - last); else @@ -261,23 +324,22 @@ gtmr_intr(void *arg) struct cpu_info * const ci = curcpu(); struct clockframe * const cf = arg; struct gtmr_softc * const sc = >mr_sc; + uint32_t ctl; - arm_isb(); - - const uint32_t ctl = gtmr_cntv_ctl_read(); + ctl = gtmr_read_ctl(sc); if ((ctl & CNTCTL_ISTATUS) == 0) return 0; - arm_isb(); - gtmr_cntv_ctl_write(0); + ctl |= CNTCTL_IMASK; + gtmr_write_ctl(sc, ctl); - const uint64_t now = gtmr_read_cntvct(sc); + const uint64_t now = gtmr_read_cntct(sc); uint64_t delta = now - ci->ci_lastintr; #ifdef DIAGNOSTIC struct gtmr_percpu *pc = NULL; if (!ISSET(sc->sc_flags, GTMR_FLAG_SUN50I_A64_UNSTABLE_TIMER)) { - const uint64_t then = gtmr_cntv_cval_read(); + const uint64_t then = sc->sc_physical ? gtmr_cntp_cval_read() : gtmr_cntv_cval_read(); pc = percpu_getref(sc->sc_percpu); KASSERTMSG(then <= now, "%"PRId64, now - then); KASSERTMSG(then + pc->pc_delta >= ci->ci_lastintr + sc->sc_autoinc, @@ -304,13 +366,15 @@ gtmr_intr(void *arg) arm_isb(); if (ISSET(sc->sc_flags, GTMR_FLAG_SUN50I_A64_UNSTABLE_TIMER)) { - gtmr_cntv_cval_write(now + sc->sc_autoinc - delta); + gtmr_write_cval(sc, now + sc->sc_autoinc - delta); } else { - gtmr_cntv_tval_write(sc->sc_autoinc - delta); + gtmr_write_tval(sc, sc->sc_autoinc - delta); } - arm_isb(); - gtmr_cntv_ctl_write(CNTCTL_ENABLE); + ctl = gtmr_read_ctl(sc); + ctl &= ~CNTCTL_IMASK; + ctl |= CNTCTL_ENABLE; + gtmr_write_ctl(sc, ctl); ci->ci_lastintr = now; @@ -338,6 +402,6 @@ static u_int gtmr_get_timecount(struct timecounter *tc) { struct gtmr_softc * const sc = tc->tc_priv; - arm_isb(); // we want the time NOW, not some instructions later. - return (u_int) gtmr_read_cntvct(sc); + + return (u_int) gtmr_read_cntct(sc); } Index: src/sys/arch/arm/cortex/gtmr_var.h diff -u src/sys/arch/arm/cortex/gtmr_var.h:1.11 src/sys/arch/arm/cortex/gtmr_var.h:1.11.4.1 --- src/sys/arch/arm/cortex/gtmr_var.h:1.11 Sun Sep 16 13:21:36 2018 +++ src/sys/arch/arm/cortex/gtmr_var.h Tue Aug 13 14:57:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: gtmr_var.h,v 1.11 2018/09/16 13:21:36 jmcneill Exp $ */ +/* $NetBSD: gtmr_var.h,v 1.11.4.1 2019/08/13 14:57:50 martin Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. * All rights reserved. @@ -40,6 +40,7 @@ struct gtmr_softc { uint32_t sc_flags; #define GTMR_FLAG_SUN50I_A64_UNSTABLE_TIMER __BIT(0) u_long sc_autoinc; + bool sc_physical; void *sc_global_ih; #ifdef DIAGNOSTIC percpu_t *sc_percpu; Index: src/sys/arch/arm/include/armreg.h diff -u src/sys/arch/arm/include/armreg.h:1.127 src/sys/arch/arm/include/armreg.h:1.127.2.1 --- src/sys/arch/arm/include/armreg.h:1.127 Thu May 2 15:37:10 2019 +++ src/sys/arch/arm/include/armreg.h Tue Aug 13 14:57:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: armreg.h,v 1.127 2019/05/02 15:37:10 skrll Exp $ */ +/* $NetBSD: armreg.h,v 1.127.2.1 2019/08/13 14:57:50 martin Exp $ */ /* * Copyright (c) 1998, 2001 Ben Harris @@ -990,6 +990,18 @@ gtmr_cntv_ctl_write(uint32_t val) armreg_cntv_ctl_write(val); } + +/* + * Counter-timer Physical Timer Control register + */ + +static inline uint32_t +gtmr_cntp_ctl_read(void) +{ + + return armreg_cntp_ctl_read(); +} + static inline void gtmr_cntp_ctl_write(uint32_t val) { @@ -999,6 +1011,24 @@ gtmr_cntp_ctl_write(uint32_t val) /* + * Counter-timer Physical Timer TimerValue register + */ +static inline uint32_t +gtmr_cntp_tval_read(void) +{ + + return armreg_cntp_tval_read(); +} + +static inline void +gtmr_cntp_tval_write(uint32_t val) +{ + + armreg_cntp_tval_write(val); +} + + +/* * Counter-timer Virtual Timer TimerValue register */ static inline uint32_t @@ -1017,6 +1047,24 @@ gtmr_cntv_tval_write(uint32_t val) /* + * Counter-timer Physical Timer CompareValue register + */ +static inline uint64_t +gtmr_cntp_cval_read(void) +{ + + return armreg_cntp_cval_read(); +} + +static inline void +gtmr_cntp_cval_write(uint64_t val) +{ + + armreg_cntp_cval_write(val); +} + + +/* * Counter-timer Virtual Timer CompareValue register */ static inline uint64_t