> Date: Tue, 01 Aug 2023 16:02:17 -0400
> From: Brad Spencer <b...@anduin.eldar.org>
> 
> Taylor R Campbell <riastr...@netbsd.org> writes:
> 
> > So I just added a printf to the kernel in case this jump happens.  Can
> > you update to xen_clock.c 1.15 (and sys/arch/x86/include/cpu.h 1.135)
> > and try again?
> 
> Sure...

Correction: xen_clock.c 1.16 and sys/arch/x86/include/cpu.h 1.136
(missed a spot).

> >> If the dtrace does continue to run, sometimes, it is impossible to exit
> >> with CTRL-C.  The process seems stuck in this:
> >> 
> >> [ 4261.7158728] load: 2.64  cmd: dtrace 3295 [xclocv] 0.01u 0.02s 0% 7340k
> >
> > Interesting.  If this is reproducible, can you enter crash or ddb and
> > get a stack trace for the dtrace process, as well as output from ps,
> > ps/w, and `show all tstiles'?
> 
> It appears to be reproduceable..  in the sense that I encountered it a
> couple of times doing exactly the same workload test.  I am more or less
> completely unsure as to what the trigger is, however.  I probably should
> have mentioned, but when this happened the last time, I did have other
> newly created processes hang in tstile (the one in particular that I
> noticed was 'fortune' from a ssh attempt .. it got stuck on login and
> when I did a CTRL-T tstile was shown).

`show all tstiles' output in crash or ddb would definitely be helpful
here.

> I also probably should have mentioned that the DOM0 (NOT the DOMU) that
> the target system is running under has HZ set to 1000.  This is mostly
> to help keep the ntpd and chronyd happy on the Xen guests.  If the DOM0
> is left at 100 the drift can be too much on the DOMU systems.  Been
> running like this for a long time...

Interesting.  Why would the dom0's HZ choice a difference?  Nothing
in the guest should depend substantively on the host's tick rate.

A NetBSD XEN3_DOM0 kernel periodically updates the hypervisor with a
real-time clock derived from NTP (the `timepush' callout in
xen_clock.c), but the period between updates is 53 sec + 3 ticks, and
it's hard to imagine that setting the clock every 53.03 sec vs every
53.003 sec should make any difference for whether guests drift.

The resolution of the real-time clock sent to NTP is 1/hz, because
resettodr uses getmicrotime instead of microtime, but while that might
introduce jitter from rounding, I'm not sure it should cause
persistent drift in one direction or the other and I don't think
guests are likely to periodically query the Xen wall clock time often
enough for this jitter to matter.

Does the dom0 have any substantive continuous influence on domU
scheduling and timing?  I always assumed the hypervisor would have all
the say in that.

As an aside, I wonder whether it's even worthwhile to run ntpd or
chronyd on the domU instead of just letting the dom0 set it and
arranging to do the equivalent of inittodr periodically in the domU?

Can you try the attached patch on a dom0 and see if you still observe
drift?
>From 639672fef2a0a6959161b6e882e16128b1340c69 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastr...@netbsd.org>
Date: Tue, 1 Aug 2023 21:58:45 +0000
Subject: [PATCH] WIP: push real-time clock directly from nanotime to
 hypervisor

Bypass resettodr's use of getmicrotime, and any overhead from
rtc_set_ymdhms.
---
 sys/arch/xen/xen/xen_clock.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/sys/arch/xen/xen/xen_clock.c b/sys/arch/xen/xen/xen_clock.c
index e36ec38ba758..fc2fa95490c4 100644
--- a/sys/arch/xen/xen/xen_clock.c
+++ b/sys/arch/xen/xen/xen_clock.c
@@ -988,8 +988,26 @@ fail:      sysctl_teardown(&log);
 static void
 xen_timepush_intr(void *cookie)
 {
+#if 1
+       struct timespec now;
+       int error;
 
+       nanotime(&now);
+       error = HYPERVISOR_platform_op(&(xen_platform_op_t) {
+               .cmd = XENPF_settime,
+               .u = {
+                       .settime = {
+                               .secs = now.tv_sec,
+                               .nsecs = now.tv_nsec,
+                               .system_time = xen_global_systime_ns(),
+                       },
+               },
+       });
+       if (error)
+               printf("%s: XENPF_settime failed: %d\n", __func__, error);
+#else
        resettodr();
+#endif
        if (xen_timepush.ticks)
                callout_schedule(&xen_timepush.ch, xen_timepush.ticks);
 }
@@ -1090,15 +1108,22 @@ xen_rtc_set(struct todr_chip_handle *todr, struct 
timeval *tvp)
                clock_secs_to_ymdhms(tvp->tv_sec, &dt);
                rtc_set_ymdhms(NULL, &dt);
 
+#if 1
+               __USE(op);
+               __USE(systime_ns);
+               return 0;
+#else
                /* Get the global system time so we can preserve it.  */
                systime_ns = xen_global_systime_ns();
 
                /* Set the hypervisor wall clock time.  */
+               /* XXX zero it first? (`mbz' field probably must be zero) */
                op.cmd = XENPF_settime;
                op.u.settime.secs = tvp->tv_sec;
                op.u.settime.nsecs = tvp->tv_usec * 1000;
                op.u.settime.system_time = systime_ns;
                return HYPERVISOR_platform_op(&op);
+#endif
        }
 #endif
 

Reply via email to