Date: Sat, 6 Sep 2014 13:21:07 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271189 - head/sys/arm/arm Message-ID: <201409061321.s86DL7BA095886@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andrew Date: Sat Sep 6 13:21:07 2014 New Revision: 271189 URL: http://svnweb.freebsd.org/changeset/base/271189 Log: Allow us to use the virtual timer. It is currently disabled, but should be usable as the default timer in place of the physical timer. We are guaranteed to have access to the virtual timer, but when running under a hypervisor may not have access to the physical. Differential Revision: https://reviews.freebsd.org/D588 Modified: head/sys/arm/arm/generic_timer.c Modified: head/sys/arm/arm/generic_timer.c ============================================================================== --- head/sys/arm/arm/generic_timer.c Sat Sep 6 11:19:12 2014 (r271188) +++ head/sys/arm/arm/generic_timer.c Sat Sep 6 13:21:07 2014 (r271189) @@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$"); #define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */ #define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */ -#define GT_CNTKCTL_EVNTI (1 << 4) /* Virtual counter event bits */ +#define GT_CNTKCTL_EVNTI (0xf << 4) /* Virtual counter event bits */ #define GT_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter event transition */ #define GT_CNTKCTL_EVNTEN (1 << 2) /* Enables virtual counter events */ #define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */ @@ -78,6 +78,7 @@ struct arm_tmr_softc { void *ihl[4]; uint32_t clkfreq; struct eventtimer et; + bool physical; }; static struct arm_tmr_softc *arm_tmr_sc = NULL; @@ -101,81 +102,83 @@ static struct timecounter arm_tmr_timeco .tc_quality = 1000, }; -static inline int +static int get_freq(void) { uint32_t val; + /* cntfrq */ __asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); return (val); } -static inline int -set_freq(uint32_t val) -{ - - __asm volatile("mcr p15, 0, %[val], c14, c0, 0" : : - [val] "r" (val)); - isb(); - - return (val); -} - - -static inline long -get_cntpct(void) +static long +get_cntxct(bool physical) { uint64_t val; - __asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val)); + isb(); + if (physical) + /* cntpct */ + __asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val)); + else + /* cntvct */ + __asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (val)); return (val); } -static inline int -set_ctrl(uint32_t val) +static int +set_ctrl(uint32_t val, bool physical) { - __asm volatile("mcr p15, 0, %[val], c14, c2, 1" : : - [val] "r" (val)); + if (physical) + /* cntp_ctl */ + __asm volatile("mcr p15, 0, %[val], c14, c2, 1" : : + [val] "r" (val)); + else + /* cntv_ctl */ + __asm volatile("mcr p15, 0, %[val], c14, c3, 1" : : + [val] "r" (val)); isb(); return (0); } -static inline int -set_tval(uint32_t val) +static int +set_tval(uint32_t val, bool physical) { - __asm volatile("mcr p15, 0, %[val], c14, c2, 0" : : - [val] "r" (val)); + if (physical) + /* cntp_tval */ + __asm volatile("mcr p15, 0, %[val], c14, c2, 0" : : + [val] "r" (val)); + else + /* cntv_tval */ + __asm volatile("mcr p15, 0, %[val], c14, c3, 0" : : + [val] "r" (val)); isb(); return (0); } -static inline int -get_ctrl(void) -{ - uint32_t val; - - __asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); - - return (val); -} - -static inline int -get_tval(void) +static int +get_ctrl(bool physical) { uint32_t val; - __asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); + if (physical) + /* cntp_ctl */ + __asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); + else + /* cntv_ctl */ + __asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); return (val); } -static inline void +static void disable_user_access(void) { uint32_t cntkctl; @@ -191,7 +194,7 @@ static unsigned arm_tmr_get_timecount(struct timecounter *tc) { - return (get_cntpct()); + return (get_cntxct(arm_tmr_sc->physical)); } static int @@ -204,11 +207,11 @@ arm_tmr_start(struct eventtimer *et, sbi if (first != 0) { counts = ((uint32_t)et->et_frequency * first) >> 32; - ctrl = get_ctrl(); + ctrl = get_ctrl(sc->physical); ctrl &= ~GT_CTRL_INT_MASK; ctrl |= GT_CTRL_ENABLE; - set_tval(counts); - set_ctrl(ctrl); + set_tval(counts, sc->physical); + set_ctrl(ctrl, sc->physical); return (0); } @@ -219,11 +222,14 @@ arm_tmr_start(struct eventtimer *et, sbi static int arm_tmr_stop(struct eventtimer *et) { + struct arm_tmr_softc *sc; int ctrl; - ctrl = get_ctrl(); + sc = (struct arm_tmr_softc *)et->et_priv; + + ctrl = get_ctrl(sc->physical); ctrl &= GT_CTRL_ENABLE; - set_ctrl(ctrl); + set_ctrl(ctrl, sc->physical); return (0); } @@ -235,10 +241,10 @@ arm_tmr_intr(void *arg) int ctrl; sc = (struct arm_tmr_softc *)arg; - ctrl = get_ctrl(); + ctrl = get_ctrl(sc->physical); if (ctrl & GT_CTRL_INT_STAT) { ctrl |= GT_CTRL_INT_MASK; - set_ctrl(ctrl); + set_ctrl(ctrl, sc->physical); } if (sc->et.et_active) @@ -295,12 +301,14 @@ arm_tmr_attach(device_t dev) if (bus_alloc_resources(dev, timer_spec, sc->res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); - }; + } + + sc->physical = true; arm_tmr_sc = sc; - /* Setup secure and non-secure IRQs handler */ - for (i = 0; i < 2; i++) { + /* Setup secure, non-secure and virtual IRQs handler */ + for (i = 0; i < 3; i++) { error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK, arm_tmr_intr, NULL, sc, &sc->ihl[i]); if (error) { @@ -381,10 +389,10 @@ DELAY(int usec) else counts = usec * counts_per_usec; - first = get_cntpct(); + first = get_cntxct(arm_tmr_sc->physical); while (counts > 0) { - last = get_cntpct(); + last = get_cntxct(arm_tmr_sc->physical); counts -= (int32_t)(last - first); first = last; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409061321.s86DL7BA095886>