svn commit: r263007 - head/sys/dev/xen/timer
Roger Pau Monné
royger at FreeBSD.org
Tue Mar 11 10:16:18 UTC 2014
Author: royger
Date: Tue Mar 11 10:16:17 2014
New Revision: 263007
URL: http://svnweb.freebsd.org/changeset/base/263007
Log:
xen: rework xen timer so it can be used early in boot process
This should not introduce any functional change, and makes the
functions suitable to be called before we have actually mapped the
vcpu_info struct on a per-cpu basis.
Approved by: gibbs
Sponsored by: Citrix Systems R&D
dev/xen/timer/timer.c:
- Remove citrical_{enter/exit}, the clock code will already be called
with preemption disabled when needed. Add a comment to that regard
in xentimer_get_timecount.
- Allow xen_fetch_vcpu_time to be called with a specifc vcpu_info
that will be used to fetch current time.
- Assert that xentimer_et_start will always be called with preemption
disabled.
Modified:
head/sys/dev/xen/timer/timer.c
Modified: head/sys/dev/xen/timer/timer.c
==============================================================================
--- head/sys/dev/xen/timer/timer.c Tue Mar 11 10:15:25 2014 (r263006)
+++ head/sys/dev/xen/timer/timer.c Tue Mar 11 10:16:17 2014 (r263007)
@@ -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_in
/**
* \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);
More information about the svn-src-all
mailing list