Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-6]: src Pull up following revision(s) (requested by pettai in tic...



details:   https://anonhg.NetBSD.org/src/rev/8a609269154a
branches:  netbsd-6
changeset: 776479:8a609269154a
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Oct 20 13:28:20 2013 +0000

description:
Pull up following revision(s) (requested by pettai in ticket #965):
        sys/arch/x86/x86/vmt.c: revision 1.8
        share/man/man4/man4.x86/vmt.4: revision 1.4
Synchronize the clock periodically in vmt(4).
Add periodic clock synchronization to vmt(4) so that the guest clock
remains synchronized even when the host is suspended (which is a very
typical situation in a laptop).
Do this by default once per minute, but provide a sysctl to tune this
value (machdep.vmt0.clock_sync.period).
Sent to tech-kern@ for review and addressed a couple of issues.

diffstat:

 share/man/man4/man4.x86/vmt.4 |   23 ++++++-
 sys/arch/x86/x86/vmt.c        |  131 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 151 insertions(+), 3 deletions(-)

diffs (259 lines):

diff -r 450a2603d5d0 -r 8a609269154a share/man/man4/man4.x86/vmt.4
--- a/share/man/man4/man4.x86/vmt.4     Sun Oct 20 13:25:02 2013 +0000
+++ b/share/man/man4/man4.x86/vmt.4     Sun Oct 20 13:28:20 2013 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: vmt.4,v 1.3 2011/10/18 14:25:06 wiz Exp $
+.\"    $NetBSD: vmt.4,v 1.3.4.1 2013/10/20 13:28:20 bouyer Exp $
 .\"    $OpenBSD: vmt.4,v 1.4 2010/10/26 05:07:31 jmc Exp $
 .\"
 .\" Copyright (c) 2008 Marco Peereboom <marco%openbsd.org@localhost>
@@ -15,7 +15,7 @@
 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 .\" ACTION OF CONTRACT, NEGLIGENCE OR TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.Dd October 18, 2011
+.Dd March 16, 2013
 .Dt VMT 4 x86
 .Os
 .Sh NAME
@@ -44,6 +44,25 @@
 .Pp
 .Nm
 reports the guest's hostname and first non-loopback IP address to the host.
+.Ss Clock synchronization
+The
+.Nm
+driver synchronizes the virtual machine's clock with the host clock in the
+following situations:
+.Bl -bullet
+.It
+When the virtual machine resumes after having been suspended.
+.It
+Periodically with the interval indicated by the
+.Va machdep.vmt0.clock_sync.period
+.Xr sysctl 8
+variable.
+This is done so that the virtual machine can keep its clock synchronized
+when the host is suspended, because in this case the
+.Nm
+driver receives no notification of such an event.
+Setting this tunable to zero disables clock synchronization.
+.El
 .Sh SEE ALSO
 .\" .Xr cpu 4 ,
 .Xr powerd 8
diff -r 450a2603d5d0 -r 8a609269154a sys/arch/x86/x86/vmt.c
--- a/sys/arch/x86/x86/vmt.c    Sun Oct 20 13:25:02 2013 +0000
+++ b/sys/arch/x86/x86/vmt.c    Sun Oct 20 13:28:20 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vmt.c,v 1.7 2011/10/21 10:10:28 jmcneill Exp $ */
+/* $NetBSD: vmt.c,v 1.7.8.1 2013/10/20 13:28:20 bouyer Exp $ */
 /* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */
 
 /*
@@ -36,6 +36,7 @@
 #include <sys/socket.h>
 #include <sys/timetc.h>
 #include <sys/module.h>
+#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
@@ -182,6 +183,7 @@
 struct vmt_softc {
        device_t                sc_dev;
 
+       struct sysctllog        *sc_log;
        struct vm_rpc           sc_tclo_rpc;
        bool                    sc_tclo_rpc_open;
        char                    *sc_rpc_buf;
@@ -193,6 +195,10 @@
        struct callout          sc_tick;
        struct callout          sc_tclo_tick;
 
+#define VMT_CLOCK_SYNC_PERIOD_SECONDS 60
+       int                     sc_clock_sync_period_seconds;
+       struct callout          sc_clock_sync_tick;
+
        struct vmt_event        sc_ev_power;
        struct vmt_event        sc_ev_reset;
        struct vmt_event        sc_ev_sleep;
@@ -204,6 +210,10 @@
 CFATTACH_DECL_NEW(vmt, sizeof(struct vmt_softc),
        vmt_match, vmt_attach, vmt_detach, NULL);
 
+static int vmt_sysctl_setup_root(device_t);
+static int vmt_sysctl_setup_clock_sync(device_t, const struct sysctlnode *);
+static int vmt_sysctl_update_clock_sync_period(SYSCTLFN_PROTO);
+
 static void vm_cmd(struct vm_backdoor *);
 static void vm_ins(struct vm_backdoor *);
 static void vm_outs(struct vm_backdoor *);
@@ -230,6 +240,7 @@
 
 static void vmt_tick(void *);
 static void vmt_tclo_tick(void *);
+static void vmt_clock_sync_tick(void *);
 static bool vmt_shutdown(device_t, int);
 static void vmt_pswitch_event(void *);
 
@@ -294,14 +305,27 @@
 static void
 vmt_attach(device_t parent, device_t self, void *aux)
 {
+       int rv;
        struct vmt_softc *sc = device_private(self);
 
        aprint_naive("\n");
        aprint_normal(": %s\n", vmt_type());
 
        sc->sc_dev = self;
+       sc->sc_log = NULL;
+
        callout_init(&sc->sc_tick, 0);
        callout_init(&sc->sc_tclo_tick, 0);
+       callout_init(&sc->sc_clock_sync_tick, 0);
+
+       sc->sc_clock_sync_period_seconds = VMT_CLOCK_SYNC_PERIOD_SECONDS;
+
+       rv = vmt_sysctl_setup_root(self);
+       if (rv != 0) {
+               aprint_error_dev(self, "failed to initialize sysctl "
+                   "(err %d)\n", rv);
+               goto free;
+       }
 
        sc->sc_rpc_buf = kmem_alloc(VMT_RPC_BUFLEN, KM_SLEEP);
        if (sc->sc_rpc_buf == NULL) {
@@ -346,6 +370,10 @@
        callout_schedule(&sc->sc_tclo_tick, hz);
        sc->sc_tclo_ping = 1;
 
+       callout_setfunc(&sc->sc_clock_sync_tick, vmt_clock_sync_tick, sc);
+       callout_schedule(&sc->sc_clock_sync_tick,
+           mstohz(sc->sc_clock_sync_period_seconds * 1000));
+
        vmt_sync_guest_clock(sc);
 
        return;
@@ -354,6 +382,8 @@
        if (sc->sc_rpc_buf)
                kmem_free(sc->sc_rpc_buf, VMT_RPC_BUFLEN);
        pmf_device_register(self, NULL, NULL);
+       if (sc->sc_log)
+               sysctl_teardown(&sc->sc_log);
 }
 
 static int
@@ -376,12 +406,111 @@
        callout_halt(&sc->sc_tclo_tick, NULL);
        callout_destroy(&sc->sc_tclo_tick);
 
+       callout_halt(&sc->sc_clock_sync_tick, NULL);
+       callout_destroy(&sc->sc_clock_sync_tick);
+
        if (sc->sc_rpc_buf)
                kmem_free(sc->sc_rpc_buf, VMT_RPC_BUFLEN);
 
+       if (sc->sc_log) {
+               sysctl_teardown(&sc->sc_log);
+               sc->sc_log = NULL;
+       }
+
        return 0;
 }
 
+static int
+vmt_sysctl_setup_root(device_t self)
+{
+       const struct sysctlnode *machdep_node, *vmt_node;
+       struct vmt_softc *sc = device_private(self);
+       int rv;
+
+       rv = sysctl_createv(&sc->sc_log, 0, NULL, &machdep_node,
+           CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
+           NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
+       if (rv != 0)
+               goto fail;
+
+       rv = sysctl_createv(&sc->sc_log, 0, &machdep_node, &vmt_node,
+           0, CTLTYPE_NODE, device_xname(self), NULL,
+           NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
+       if (rv != 0)
+               goto fail;
+
+       rv = vmt_sysctl_setup_clock_sync(self, vmt_node);
+       if (rv != 0)
+               goto fail;
+
+       return 0;
+
+fail:
+       sysctl_teardown(&sc->sc_log);
+       sc->sc_log = NULL;
+
+       return rv;
+}
+
+static int
+vmt_sysctl_setup_clock_sync(device_t self, const struct sysctlnode *root_node)
+{
+       const struct sysctlnode *node, *period_node;
+       struct vmt_softc *sc = device_private(self);
+       int rv;
+
+       rv = sysctl_createv(&sc->sc_log, 0, &root_node, &node,
+           0, CTLTYPE_NODE, "clock_sync", NULL,
+           NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
+       if (rv != 0)
+               return rv;
+
+       rv = sysctl_createv(&sc->sc_log, 0, &node, &period_node,
+           CTLFLAG_READWRITE, CTLTYPE_INT, "period",
+           SYSCTL_DESCR("Period, in seconds, at which to update the "
+               "guest's clock"),
+           vmt_sysctl_update_clock_sync_period, 0, (void *)sc, 0,
+           CTL_CREATE, CTL_EOL);
+       return rv;
+}
+
+static int
+vmt_sysctl_update_clock_sync_period(SYSCTLFN_ARGS)
+{
+       int error, period;
+       struct sysctlnode node;
+       struct vmt_softc *sc;
+
+       node = *rnode;
+       sc = (struct vmt_softc *)node.sysctl_data;
+
+       period = sc->sc_clock_sync_period_seconds;
+       node.sysctl_data = &period;
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error || newp == NULL)
+               return error;
+
+       if (sc->sc_clock_sync_period_seconds != period) {
+               callout_halt(&sc->sc_clock_sync_tick, NULL);
+               sc->sc_clock_sync_period_seconds = period;
+               if (sc->sc_clock_sync_period_seconds > 0)
+                       callout_schedule(&sc->sc_clock_sync_tick,
+                           mstohz(sc->sc_clock_sync_period_seconds * 1000));
+       }
+       return 0;
+}
+
+static void
+vmt_clock_sync_tick(void *xarg)
+{
+       struct vmt_softc *sc = xarg;
+
+       vmt_sync_guest_clock(sc);
+
+       callout_schedule(&sc->sc_clock_sync_tick,
+           mstohz(sc->sc_clock_sync_period_seconds * 1000));
+}
+
 static void
 vmt_update_guest_uptime(struct vmt_softc *sc)
 {



Home | Main Index | Thread Index | Old Index