diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2017-01-19 10:16:23 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2017-01-19 10:16:23 +0000 |
commit | fcbb21d8a2a9a846b6b3ab6ca2eced979ec7c906 (patch) | |
tree | e77b75feae7a0fc52a3d51ac9f2c8631b0559ad5 /sys | |
parent | 4ff33f46c3e1ff4e383176dbe0fb32c8a3c3e921 (diff) |
Export the host time to the guest, add it as a timedelta sensor in vmmci(4)
OK kettenis@ mlarkin@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/vmmci.c | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/sys/dev/pci/vmmci.c b/sys/dev/pci/vmmci.c index 23f86c5e4ea..7d79fca958e 100644 --- a/sys/dev/pci/vmmci.c +++ b/sys/dev/pci/vmmci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmmci.c,v 1.1 2017/01/13 14:37:32 reyk Exp $ */ +/* $OpenBSD: vmmci.c,v 1.2 2017/01/19 10:16:22 reyk Exp $ */ /* * Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org> @@ -44,6 +44,8 @@ struct vmmci_softc { struct virtio_softc *sc_virtio; enum vmmci_cmd sc_cmd; unsigned int sc_interval; + struct ksensordev sc_sensordev; + struct ksensor sc_sensor; struct timeout sc_tick; }; @@ -51,6 +53,8 @@ int vmmci_match(struct device *, void *, void *); void vmmci_attach(struct device *, struct device *, void *); int vmmci_config_change(struct virtio_softc *); +void vmmci_tick(void *); +void vmmci_tick_hook(struct device *); struct cfattach vmmci_ca = { sizeof(struct vmmci_softc), @@ -59,6 +63,14 @@ struct cfattach vmmci_ca = { NULL }; +/* Configuration registers */ +#define VMMCI_CONFIG_COMMAND 0 +#define VMMCI_CONFIG_TIME_SEC 4 +#define VMMCI_CONFIG_TIME_USEC 12 + +/* Feature bits */ +#define VMMCI_F_TIMESYNC (1<<0) + struct cfdriver vmmci_cd = { NULL, "vmmci", DV_DULL }; @@ -77,6 +89,7 @@ vmmci_attach(struct device *parent, struct device *self, void *aux) { struct vmmci_softc *sc = (struct vmmci_softc *)self; struct virtio_softc *vsc = (struct virtio_softc *)parent; + uint32_t features; if (vsc->sc_child != NULL) panic("already attached to something else"); @@ -87,7 +100,19 @@ vmmci_attach(struct device *parent, struct device *self, void *aux) vsc->sc_ipl = IPL_NET; sc->sc_virtio = vsc; - virtio_negotiate_features(vsc, 0, NULL); + features = VMMCI_F_TIMESYNC; + features = virtio_negotiate_features(vsc, features, NULL); + + if (features & VMMCI_F_TIMESYNC) { + strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensordev.xname)); + sc->sc_sensor.type = SENSOR_TIMEDELTA; + sc->sc_sensor.status = SENSOR_S_UNKNOWN; + sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); + sensordev_install(&sc->sc_sensordev); + + config_mountroot(self, vmmci_tick_hook); + } printf("\n"); } @@ -96,8 +121,10 @@ int vmmci_config_change(struct virtio_softc *vsc) { struct vmmci_softc *sc = (struct vmmci_softc *)vsc->sc_child; - int cmd = virtio_read_device_config_1(vsc, 0); + int cmd; + /* Check for command */ + cmd = virtio_read_device_config_1(vsc, VMMCI_CONFIG_COMMAND); if (cmd == sc->sc_cmd) return (0); sc->sc_cmd = cmd; @@ -119,3 +146,38 @@ vmmci_config_change(struct virtio_softc *vsc) return (1); } + +void +vmmci_tick(void *arg) +{ + struct vmmci_softc *sc = arg; + struct virtio_softc *vsc = sc->sc_virtio; + struct timeval *guest = &sc->sc_sensor.tv; + struct timeval host, diff; + + microtime(guest); + + /* Update time delta sensor */ + host.tv_sec = virtio_read_device_config_8(vsc, VMMCI_CONFIG_TIME_SEC); + host.tv_usec = virtio_read_device_config_8(vsc, VMMCI_CONFIG_TIME_USEC); + + if (host.tv_usec > 0) { + timersub(guest, &host, &diff); + + sc->sc_sensor.value = (uint64_t)diff.tv_sec * 1000000000LL + + (uint64_t)diff.tv_usec * 1000LL; + sc->sc_sensor.status = SENSOR_S_OK; + } else + sc->sc_sensor.status = SENSOR_S_UNKNOWN; + + timeout_add_sec(&sc->sc_tick, 15); +} + +void +vmmci_tick_hook(struct device *self) +{ + struct vmmci_softc *sc = (struct vmmci_softc *)self; + + timeout_set(&sc->sc_tick, vmmci_tick, sc); + vmmci_tick(sc); +} |