diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2017-01-21 11:23:15 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2017-01-21 11:23:15 +0000 |
commit | 8ff75b4936e9c8d996abea80cd133d1d75dd4446 (patch) | |
tree | 5fe616eb69393902e7bac7f67f71b4f3a31b55d1 /sys/dev/pv | |
parent | a5fb8bb27e1d4907bef569ffe7db669716d9c63a (diff) |
Move vmmci.c to sys/dev/pv/vmmci.c
virtio itself is not PCI, it is a paravirtual bus on top of either PCI
or MMIO (arm). This is the second step of moving the virtio files to
dev/pv. No functional change.
Moving the file is done by removing and adding it again - the old
history can be found in the Attic of sys/dev/pci/vmmci.c.
no objections from sf@ mlarkin@
Diffstat (limited to 'sys/dev/pv')
-rw-r--r-- | sys/dev/pv/vmmci.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/sys/dev/pv/vmmci.c b/sys/dev/pv/vmmci.c new file mode 100644 index 00000000000..1dfd5e7eaf2 --- /dev/null +++ b/sys/dev/pv/vmmci.c @@ -0,0 +1,183 @@ +/* $OpenBSD: vmmci.c,v 1.1 2017/01/21 11:23:14 reyk Exp $ */ + +/* + * Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/timeout.h> +#include <sys/signalvar.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/pool.h> +#include <sys/proc.h> + +#include <machine/bus.h> + +#include <dev/pv/virtioreg.h> +#include <dev/pv/virtiovar.h> +#include <dev/pv/pvvar.h> +#include <dev/rndvar.h> + +enum vmmci_cmd { + VMMCI_NONE = 0, + VMMCI_SHUTDOWN, + VMMCI_REBOOT, +}; + +struct vmmci_softc { + struct device sc_dev; + 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; +}; + +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), + vmmci_match, + vmmci_attach, + 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 +}; + +int +vmmci_match(struct device *parent, void *match, void *aux) +{ + struct virtio_softc *va = aux; + if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_VMMCI) + return (1); + return (0); +} + +void +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"); + + vsc->sc_child = self; + vsc->sc_nvqs = 0; + vsc->sc_config_change = vmmci_config_change; + vsc->sc_ipl = IPL_NET; + sc->sc_virtio = vsc; + + 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"); +} + +int +vmmci_config_change(struct virtio_softc *vsc) +{ + struct vmmci_softc *sc = (struct vmmci_softc *)vsc->sc_child; + 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; + + switch (cmd) { + case VMMCI_NONE: + /* no action */ + break; + case VMMCI_SHUTDOWN: + pvbus_shutdown(&sc->sc_dev); + break; + case VMMCI_REBOOT: + pvbus_reboot(&sc->sc_dev); + break; + default: + printf("%s: invalid command %d\n", sc->sc_dev.dv_xname, cmd); + break; + } + + 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); +} |