On Wed, Jul 25, 2012 at 11:14, Matthew Dempsky wrote:
> In vmt_tick() we could notice anytime the reported sensor value jumps
> significantly and then wind forward the clocks like we do when
> recovering from ACPI sleep.

I like this, and I think it even works.  Scary warnings about no
locking in kern_tc.c aside.  I had a look, and there's three functions.

tc_setclock - doesn't seem to do much itself.  What are the
consquences of timehands->th_offset getting raced?
timeout_adjust_ticks - does its own locking, safe.
tc_windup - this function is "slightly magic".  mostly operates on the
next timehands, then swaps at the end.  I think calling two windups at
the same time would be bad, but calling this in parallel with other
time code doesn't appear harmful.

So how much locking do we need?  Protect tc_windup with a mutex?
Maybe tc_setclock should operate on the next timehands as well?

Anyway, here's the diff.  I don't mean to suggest we literally want
this, but it does what I want.  Of course, if somebody wanted to test
a vm with a wrong clock, they're not going to have much luck.  Should
the vmt clock bludgeon be optional or not?

Index: vmt.c
===================================================================
RCS file: /cvs/src/sys/dev/vmt.c,v
retrieving revision 1.11
diff -u -p -r1.11 vmt.c
--- vmt.c       27 Jan 2011 21:29:25 -0000      1.11
+++ vmt.c       25 Jul 2012 19:44:20 -0000
@@ -38,6 +38,7 @@
 #include <sys/syslog.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
+#include <sys/timetc.h>
 #include <net/if.h>
 #include <netinet/in.h>
 
@@ -356,6 +357,7 @@ vmt_tick(void *xarg)
        struct vm_backdoor frame;
        struct timeval *guest = &sc->sc_sensor.tv;
        struct timeval host, diff;
+       struct timespec ts;
 
        microtime(guest);
 
@@ -374,6 +376,11 @@ vmt_tick(void *xarg)
                sc->sc_sensor.value = (u_int64_t)diff.tv_sec * 1000000000LL +
                    (u_int64_t)diff.tv_usec * 1000LL;
                sc->sc_sensor.status = SENSOR_S_OK;
+
+               if (diff.tv_sec > 60 || diff.tv_sec < -60) {
+                       TIMEVAL_TO_TIMESPEC(&host, &ts);
+                       tc_setclock(&ts);
+               }
        } else {
                sc->sc_sensor.status = SENSOR_S_UNKNOWN;
        }
@@ -381,7 +388,7 @@ vmt_tick(void *xarg)
        vmt_update_guest_info(sc);
        vmt_update_guest_uptime(sc);
 
-       timeout_add_sec(&sc->sc_tick, 15);
+       timeout_add_sec(&sc->sc_tick, 1);
 }
 
 void

Reply via email to