Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Rewrite Xen timecounter and hardclock timer.
details: https://anonhg.NetBSD.org/src/rev/e9003ce6a1a6
branches: trunk
changeset: 320272:e9003ce6a1a6
user: riastradh <riastradh%NetBSD.org@localhost>
date: Fri Jun 29 21:53:12 2018 +0000
description:
Rewrite Xen timecounter and hardclock timer.
With this change, the Xen timecounter should now be globally
monotonic, as every timecounter is supposed to be. Should also fix a
litany of races in the timecounter logic.
Proposed last year; see mailing list for further details:
https://mail-index.netbsd.org/port-xen/2017/10/31/msg009112.html
ok cherry
diffstat:
sys/arch/x86/include/cpu.h | 28 +-
sys/arch/xen/xen/clock.c | 1279 +++++++++++++++++++++++++++++--------------
2 files changed, 884 insertions(+), 423 deletions(-)
diffs (truncated from 1493 to 300 lines):
diff -r d4fe977f51b2 -r e9003ce6a1a6 sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h Fri Jun 29 20:18:36 2018 +0000
+++ b/sys/arch/x86/include/cpu.h Fri Jun 29 21:53:12 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.92 2018/06/14 14:36:46 maxv Exp $ */
+/* $NetBSD: cpu.h,v 1.93 2018/06/29 21:53:12 riastradh Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@@ -236,6 +236,32 @@
struct cpu_tss *ci_tss; /* Per-cpu TSSes; shared among LWPs */
int ci_tss_sel; /* TSS selector of this cpu */
+#ifdef XEN
+ /* Xen raw system time at which we last ran hardclock. */
+ uint64_t ci_xen_hardclock_systime_ns;
+
+ /*
+ * Last TSC-adjusted local Xen system time we observed. Used
+ * to detect whether the Xen clock has gone backwards.
+ */
+ uint64_t ci_xen_last_systime_ns;
+
+ /*
+ * Distance in nanoseconds from the local view of system time
+ * to the global view of system time, if the local time is
+ * behind the global time.
+ */
+ uint64_t ci_xen_systime_ns_skew;
+
+ /* Event counters for various pathologies that might happen. */
+ struct evcnt ci_xen_cpu_tsc_backwards_evcnt;
+ struct evcnt ci_xen_tsc_delta_negative_evcnt;
+ struct evcnt ci_xen_raw_systime_wraparound_evcnt;
+ struct evcnt ci_xen_raw_systime_backwards_evcnt;
+ struct evcnt ci_xen_systime_backwards_hardclock_evcnt;
+ struct evcnt ci_xen_missed_hardclock_evcnt;
+#endif
+
/*
* The following two are actually region_descriptors,
* but that would pollute the namespace.
diff -r d4fe977f51b2 -r e9003ce6a1a6 sys/arch/xen/xen/clock.c
--- a/sys/arch/xen/xen/clock.c Fri Jun 29 20:18:36 2018 +0000
+++ b/sys/arch/xen/xen/clock.c Fri Jun 29 21:53:12 2018 +0000
@@ -1,9 +1,11 @@
-/* $NetBSD: clock.c,v 1.67 2018/06/24 13:35:33 jdolecek Exp $ */
+/* $NetBSD: clock.c,v 1.68 2018/06/29 21:53:12 riastradh Exp $ */
-/*
+/*-
+ * Copyright (c) 2017, 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
*
- * Copyright (c) 2004 Christian Limpach.
- * All rights reserved.
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,580 +16,1013 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_xen.h"
+#ifndef XEN_CLOCK_DEBUG
+#define XEN_CLOCK_DEBUG 0
+#endif
+
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.67 2018/06/24 13:35:33 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.68 2018/06/29 21:53:12 riastradh Exp $");
#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/callout.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/evcnt.h>
+#include <sys/intr.h>
+#include <sys/kernel.h>
+#include <sys/lwp.h>
+#include <sys/percpu.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/timetc.h>
-#include <sys/timevar.h>
-#include <sys/kernel.h>
-#include <sys/device.h>
-#include <sys/sysctl.h>
-
-#include <xen/xen.h>
-#include <xen/hypervisor.h>
-#include <xen/evtchn.h>
-#include <xen/xen-public/vcpu.h>
-#include <machine/cpu_counter.h>
#include <dev/clock_subr.h>
+
+#include <machine/cpu.h>
+#include <machine/cpu_counter.h>
+#include <machine/lock.h>
+
+#include <xen/evtchn.h>
+#include <xen/hypervisor.h>
+#include <xen/xen-public/vcpu.h>
+#include <xen/xen.h>
+
#include <x86/rtc.h>
-static int xen_timer_handler(void *, struct intrframe *);
-static int (*xen_timer_handler_stub)(void *) = (void *) xen_timer_handler;
-static struct intrhand *ih;
+#define NS_PER_TICK ((uint64_t)1000000000ULL/hz)
-/* A timecounter: Xen system_time extrapolated with a TSC. */
-u_int xen_get_timecount(struct timecounter*);
+static uint64_t xen_vcputime_systime_ns(void);
+static uint64_t xen_vcputime_raw_systime_ns(void);
+static void xen_wallclock_time(struct timespec *);
+static uint64_t xen_global_systime_ns(void);
+static unsigned xen_get_timecount(struct timecounter *);
+static int xen_rtc_get(struct todr_chip_handle *, struct timeval *);
+static int xen_rtc_set(struct todr_chip_handle *, struct timeval *);
+static int xen_timer_handler(void *, struct clockframe *);
+
+/*
+ * xen timecounter:
+ *
+ * Xen vCPU system time, plus an adjustment with rdtsc.
+ */
static struct timecounter xen_timecounter = {
.tc_get_timecount = xen_get_timecount,
.tc_poll_pps = NULL,
.tc_counter_mask = ~0U,
- .tc_frequency = 1000000000ULL,
+ .tc_frequency = 1000000000ULL, /* 1 GHz, i.e. units of nanoseconds */
.tc_name = "xen_system_time",
- .tc_quality = 10000 /*
- * This needs to take precedence over any hardware
- * timecounters (e.g., ACPI in Xen3 dom0), because
- * they can't correct for Xen scheduling latency.
- */
+ .tc_quality = 10000,
};
-/* These are periodically updated in shared_info, and then copied here. */
-struct shadow {
- uint64_t tsc_stamp;
- uint64_t system_time;
- unsigned long time_version; /* XXXSMP */
- uint32_t freq_mul;
- int8_t freq_shift;
- struct timespec ts;
+/*
+ * xen_global_systime_ns_stamp
+ *
+ * The latest Xen vCPU system time that has been observed on any
+ * CPU, for a global monotonic view of the Xen system time clock.
+ */
+static volatile uint64_t xen_global_systime_ns_stamp __cacheline_aligned;
+
+/*
+ * xen time of day register:
+ *
+ * Xen wall clock time, plus a Xen vCPU system time adjustment.
+ */
+static struct todr_chip_handle xen_todr_chip = {
+ .todr_gettime = xen_rtc_get,
+ .todr_settime = xen_rtc_set,
};
-/* Protects volatile variables ci_shadow & xen_clock_bias */
-static kmutex_t tmutex;
-
-/* Per CPU shadow time values */
-static volatile struct shadow ci_shadow[MAXCPUS];
-
-/* The time when the last hardclock(9) call should have taken place,
- * per cpu.
+/*
+ * xen timer interrupt handles -- per-CPU struct intrhand *
*/
-static volatile uint64_t vcpu_system_time[MAXCPUS];
-
-/*
- * The clock (as returned by xen_get_timecount) may need to be held
- * back to maintain the illusion that hardclock(9) was called when it
- * was supposed to be, not when Xen got around to scheduling us.
- */
-static volatile uint64_t xen_clock_bias[MAXCPUS];
+static struct percpu *xen_timer_ih_percpu __read_mostly;
#ifdef DOM0OPS
-/* If we're dom0, send our time to Xen every minute or so. */
-int xen_timepush_ticks = 0;
-static callout_t xen_timepush_co;
+/*
+ * xen timepush state:
+ *
+ * Callout to periodically, after a sysctl-configurable number of
+ * NetBSD ticks, set the Xen hypervisor's wall clock time.
+ */
+static struct {
+ struct callout ch;
+ int ticks;
+} xen_timepush;
+
+static void xen_timepush_init(void);
+static void xen_timepush_intr(void *);
+static int sysctl_xen_timepush(SYSCTLFN_ARGS);
#endif
-#define NS_PER_TICK (1000000000ULL/hz)
+/*
+ * startrtclock()
+ *
+ * Initialize the real-time clock from x86 machdep autoconf.
+ */
+void
+startrtclock(void)
+{
+
+ todr_attach(&xen_todr_chip);
+}
/*
- * Reads a consistent set of time-base values from Xen, into a shadow data
- * area. Must be called at splhigh (per timecounter requirements).
+ * setstatclockrate(rate)
+ *
+ * Set the statclock to run at rate, in units of ticks per second.
+ *
+ * Currently Xen does not have a separate statclock, so this is a
+ * noop; instad the statclock runs in hardclock.
*/
-static void
-get_time_values_from_xen(struct cpu_info *ci)
+void
+setstatclockrate(int rate)
+{
+}
+
+/*
+ * idle_block()
+ *
+ * Called from the idle loop when we have nothing to do but wait
+ * for an interrupt.
+ */
+void
+idle_block(void)
{
- volatile struct shadow *shadow = &ci_shadow[ci->ci_cpuid];
+ KASSERT(curcpu()->ci_ipending == 0);
+ HYPERVISOR_block();
+}
+
+/*
+ * xen_rdtsc()
+ *
+ * Read the local pCPU's tsc.
+ */
+static inline uint64_t
+xen_rdtsc(void)
+{
+ uint32_t lo, hi;
+
+ asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
+
+ return ((uint64_t)hi << 32) | lo;
+}
Home |
Main Index |
Thread Index |
Old Index