diff options
| author | Roger Pau Monné <royger@FreeBSD.org> | 2014-03-11 10:16:17 +0000 |
|---|---|---|
| committer | Roger Pau Monné <royger@FreeBSD.org> | 2014-03-11 10:16:17 +0000 |
| commit | 09982c99b2ec5df06bf084d9c0ce113c192a330b (patch) | |
| tree | f321423d5d9e9055745534e5c6c54b3517c431b4 /sys/dev/xen/timer | |
| parent | 97baeefd5b42d5f43006928126733d63379d0c46 (diff) | |
Notes
Diffstat (limited to 'sys/dev/xen/timer')
| -rw-r--r-- | sys/dev/xen/timer/timer.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/sys/dev/xen/timer/timer.c b/sys/dev/xen/timer/timer.c index 354085bc183a..6c0a140ec762 100644 --- a/sys/dev/xen/timer/timer.c +++ b/sys/dev/xen/timer/timer.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/limits.h> #include <sys/clock.h> +#include <sys/proc.h> #include <xen/xen-os.h> #include <xen/features.h> @@ -230,22 +231,22 @@ xen_fetch_vcpu_tinfo(struct vcpu_time_info *dst, struct vcpu_time_info *src) /** * \brief Get the current time, in nanoseconds, since the hypervisor booted. * + * \param vcpu vcpu_info structure to fetch the time from. + * * \note This function returns the current CPU's idea of this value, unless * it happens to be less than another CPU's previously determined value. */ static uint64_t -xen_fetch_vcpu_time(void) +xen_fetch_vcpu_time(struct vcpu_info *vcpu) { struct vcpu_time_info dst; struct vcpu_time_info *src; uint32_t pre_version; uint64_t now; volatile uint64_t last; - struct vcpu_info *vcpu = DPCPU_GET(vcpu_info); src = &vcpu->time; - critical_enter(); do { pre_version = xen_fetch_vcpu_tinfo(&dst, src); barrier(); @@ -266,16 +267,24 @@ xen_fetch_vcpu_time(void) } } while (!atomic_cmpset_64(&xen_timer_last_time, last, now)); - critical_exit(); - return (now); } static uint32_t xentimer_get_timecount(struct timecounter *tc) { + uint64_t vcpu_time; + + /* + * We don't disable preemption here because the worst that can + * happen is reading the vcpu_info area of a different CPU than + * the one we are currently running on, but that would also + * return a valid tc (and we avoid the overhead of + * critical_{enter/exit} calls). + */ + vcpu_time = xen_fetch_vcpu_time(DPCPU_GET(vcpu_info)); - return ((uint32_t)xen_fetch_vcpu_time() & UINT_MAX); + return (vcpu_time & UINT32_MAX); } /** @@ -305,7 +314,10 @@ xen_fetch_wallclock(struct timespec *ts) static void xen_fetch_uptime(struct timespec *ts) { - uint64_t uptime = xen_fetch_vcpu_time(); + uint64_t uptime; + + uptime = xen_fetch_vcpu_time(DPCPU_GET(vcpu_info)); + ts->tv_sec = uptime / NSEC_IN_SEC; ts->tv_nsec = uptime % NSEC_IN_SEC; } @@ -354,7 +366,7 @@ xentimer_intr(void *arg) struct xentimer_softc *sc = (struct xentimer_softc *)arg; struct xentimer_pcpu_data *pcpu = DPCPU_PTR(xentimer_pcpu); - pcpu->last_processed = xen_fetch_vcpu_time(); + pcpu->last_processed = xen_fetch_vcpu_time(DPCPU_GET(vcpu_info)); if (pcpu->timer != 0 && sc->et.et_active) sc->et.et_event_cb(&sc->et, sc->et.et_arg); @@ -398,7 +410,14 @@ xentimer_et_start(struct eventtimer *et, struct xentimer_softc *sc = et->et_priv; int cpu = PCPU_GET(vcpu_id); struct xentimer_pcpu_data *pcpu = DPCPU_PTR(xentimer_pcpu); + struct vcpu_info *vcpu = DPCPU_GET(vcpu_info); uint64_t first_in_ns, next_time; +#ifdef INVARIANTS + struct thread *td = curthread; +#endif + + KASSERT(td->td_critnest != 0, + ("xentimer_et_start called without preemption disabled")); /* See sbttots() for this formula. */ first_in_ns = (((first >> 32) * NSEC_IN_SEC) + @@ -415,7 +434,7 @@ xentimer_et_start(struct eventtimer *et, do { if (++i == 60) panic("can't schedule timer"); - next_time = xen_fetch_vcpu_time() + first_in_ns; + next_time = xen_fetch_vcpu_time(vcpu) + first_in_ns; error = xentimer_vcpu_start_timer(cpu, next_time); } while (error == -ETIME); |
