From owner-svn-src-all@FreeBSD.ORG Tue Mar 11 10:16:18 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 22C288F2; Tue, 11 Mar 2014 10:16:18 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 0F4ECF1F; Tue, 11 Mar 2014 10:16:18 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s2BAGHEp019047; Tue, 11 Mar 2014 10:16:17 GMT (envelope-from royger@svn.freebsd.org) Received: (from royger@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s2BAGHxE019046; Tue, 11 Mar 2014 10:16:17 GMT (envelope-from royger@svn.freebsd.org) Message-Id: <201403111016.s2BAGHxE019046@svn.freebsd.org> From: Roger Pau Monné Date: Tue, 11 Mar 2014 10:16:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r263007 - head/sys/dev/xen/timer X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Mar 2014 10:16:18 -0000 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 #include #include +#include #include #include @@ -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);