diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -110,7 +110,8 @@ uint32_t clkfreq; int irq_count; struct eventtimer et; - bool physical; + bool physical_sys; + bool physical_user; }; static struct arm_tmr_softc *arm_tmr_sc = NULL; @@ -271,7 +272,7 @@ /* Always enable the virtual timer */ cntkctl |= GT_CNTKCTL_PL0VCTEN; /* Enable the physical timer if supported */ - if (arm_tmr_sc->physical) { + if (arm_tmr_sc->physical_user) { cntkctl |= GT_CNTKCTL_PL0PCTEN; } set_el1(cntkctl, cntkctl); @@ -333,7 +334,7 @@ arm_tmr_get_timecount(struct timecounter *tc) { - return (arm_tmr_sc->get_cntxct(arm_tmr_sc->physical)); + return (arm_tmr_sc->get_cntxct(arm_tmr_sc->physical_sys)); } static int @@ -347,11 +348,11 @@ if (first != 0) { counts = ((uint32_t)et->et_frequency * first) >> 32; - ctrl = get_ctrl(sc->physical); + ctrl = get_ctrl(sc->physical_sys); ctrl &= ~GT_CTRL_INT_MASK; ctrl |= GT_CTRL_ENABLE; - set_tval(counts, sc->physical); - set_ctrl(ctrl, sc->physical); + set_tval(counts, sc->physical_sys); + set_ctrl(ctrl, sc->physical_sys); return (0); } @@ -375,7 +376,7 @@ struct arm_tmr_softc *sc; sc = (struct arm_tmr_softc *)et->et_priv; - arm_tmr_disable(sc->physical); + arm_tmr_disable(sc->physical_sys); return (0); } @@ -387,10 +388,10 @@ int ctrl; sc = (struct arm_tmr_softc *)arg; - ctrl = get_ctrl(sc->physical); + ctrl = get_ctrl(sc->physical_sys); if (ctrl & GT_CTRL_INT_STAT) { ctrl |= GT_CTRL_INT_MASK; - set_ctrl(ctrl, sc->physical); + set_ctrl(ctrl, sc->physical_sys); } if (sc->et.et_active) @@ -616,7 +617,7 @@ phandle_t node; pcell_t clock; #endif - int error; + int error, user_phys; int i, first_timer, last_timer; sc = device_get_softc(dev); @@ -680,18 +681,28 @@ * coordinated with the virtual machine manager. */ if (!HAS_PHYS) { - sc->physical = false; + sc->physical_sys = false; first_timer = GT_VIRT; last_timer = GT_VIRT; } else #endif /* Otherwise set up the secure and non-secure physical timers. */ { - sc->physical = true; + sc->physical_sys = true; first_timer = GT_PHYS_SECURE; last_timer = GT_PHYS_NONSECURE; } + /* + * The virtual timer is always available on arm and arm64, tell + * userspace to use it. + */ + sc->physical_user = false; + /* Allow use of the physical counter in userspace when available */ + if (TUNABLE_INT_FETCH("hw.userspace_allow_phys_counter", &user_phys) && + user_phys != 0) + sc->physical_user = sc->physical_sys; + arm_tmr_sc = sc; /* Setup secure, non-secure and virtual IRQs handler */ @@ -790,10 +801,10 @@ else counts = usec * counts_per_usec; - first = sc->get_cntxct(sc->physical); + first = sc->get_cntxct(sc->physical_sys); while (counts > 0) { - last = sc->get_cntxct(sc->physical); + last = sc->get_cntxct(sc->physical_sys); counts -= (int32_t)(last - first); first = last; } @@ -830,7 +841,7 @@ { vdso_th->th_algo = VDSO_TH_ALGO_ARM_GENTIM; - vdso_th->th_physical = arm_tmr_sc->physical; + vdso_th->th_physical = arm_tmr_sc->physical_user; bzero(vdso_th->th_res, sizeof(vdso_th->th_res)); return (1); }