Index: head/sys/conf/files.amd64 =================================================================== --- head/sys/conf/files.amd64 +++ head/sys/conf/files.amd64 @@ -298,12 +298,12 @@ dev/hyperv/netvsc/hn_rndis.c optional hyperv dev/hyperv/netvsc/if_hn.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv -dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_snapshot.c optional hyperv -dev/hyperv/utilities/hv_shutdown.c optional hyperv -dev/hyperv/utilities/hv_timesync.c optional hyperv +dev/hyperv/utilities/vmbus_heartbeat.c optional hyperv dev/hyperv/utilities/vmbus_ic.c optional hyperv +dev/hyperv/utilities/vmbus_shutdown.c optional hyperv +dev/hyperv/utilities/vmbus_timesync.c optional hyperv dev/hyperv/vmbus/hyperv.c optional hyperv dev/hyperv/vmbus/hyperv_busdma.c optional hyperv dev/hyperv/vmbus/vmbus.c optional hyperv pci Index: head/sys/conf/files.i386 =================================================================== --- head/sys/conf/files.i386 +++ head/sys/conf/files.i386 @@ -254,12 +254,12 @@ dev/hyperv/netvsc/hn_rndis.c optional hyperv dev/hyperv/netvsc/if_hn.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv -dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_snapshot.c optional hyperv -dev/hyperv/utilities/hv_shutdown.c optional hyperv -dev/hyperv/utilities/hv_timesync.c optional hyperv +dev/hyperv/utilities/vmbus_heartbeat.c optional hyperv dev/hyperv/utilities/vmbus_ic.c optional hyperv +dev/hyperv/utilities/vmbus_shutdown.c optional hyperv +dev/hyperv/utilities/vmbus_timesync.c optional hyperv dev/hyperv/vmbus/hyperv.c optional hyperv dev/hyperv/vmbus/hyperv_busdma.c optional hyperv dev/hyperv/vmbus/vmbus.c optional hyperv pci Index: head/sys/dev/hyperv/utilities/hv_heartbeat.c =================================================================== --- head/sys/dev/hyperv/utilities/hv_heartbeat.c +++ head/sys/dev/hyperv/utilities/hv_heartbeat.c @@ -1,152 +0,0 @@ -/*- - * Copyright (c) 2014,2016 Microsoft Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define VMBUS_HEARTBEAT_FWVER_MAJOR 3 -#define VMBUS_HEARTBEAT_FWVER \ - VMBUS_IC_VERSION(VMBUS_HEARTBEAT_FWVER_MAJOR, 0) - -#define VMBUS_HEARTBEAT_MSGVER_MAJOR 3 -#define VMBUS_HEARTBEAT_MSGVER \ - VMBUS_IC_VERSION(VMBUS_HEARTBEAT_MSGVER_MAJOR, 0) - -static int vmbus_heartbeat_probe(device_t); -static int vmbus_heartbeat_attach(device_t); - -static const struct vmbus_ic_desc vmbus_heartbeat_descs[] = { - { - .ic_guid = { .hv_guid = { - 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d} }, - .ic_desc = "Hyper-V Heartbeat" - }, - VMBUS_IC_DESC_END -}; - -static device_method_t vmbus_heartbeat_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, vmbus_heartbeat_probe), - DEVMETHOD(device_attach, vmbus_heartbeat_attach), - DEVMETHOD(device_detach, vmbus_ic_detach), - DEVMETHOD_END -}; - -static driver_t vmbus_heartbeat_driver = { - "hvheartbeat", - vmbus_heartbeat_methods, - sizeof(struct vmbus_ic_softc) -}; - -static devclass_t vmbus_heartbeat_devclass; - -DRIVER_MODULE(hv_heartbeat, vmbus, vmbus_heartbeat_driver, - vmbus_heartbeat_devclass, NULL, NULL); -MODULE_VERSION(hv_heartbeat, 1); -MODULE_DEPEND(hv_heartbeat, vmbus, 1, 1, 1); - -static void -vmbus_heartbeat_cb(struct vmbus_channel *chan, void *xsc) -{ - struct vmbus_ic_softc *sc = xsc; - struct vmbus_icmsg_hdr *hdr; - int dlen, error; - uint64_t xactid; - void *data; - - /* - * Receive request. - */ - data = sc->ic_buf; - dlen = sc->ic_buflen; - error = vmbus_chan_recv(chan, data, &dlen, &xactid); - KASSERT(error != ENOBUFS, ("icbuf is not large enough")); - if (error) - return; - - if (dlen < sizeof(*hdr)) { - device_printf(sc->ic_dev, "invalid data len %d\n", dlen); - return; - } - hdr = data; - - /* - * Update request, which will be echoed back as response. - */ - switch (hdr->ic_type) { - case VMBUS_ICMSG_TYPE_NEGOTIATE: - error = vmbus_ic_negomsg(sc, data, &dlen, - VMBUS_HEARTBEAT_FWVER, VMBUS_HEARTBEAT_MSGVER); - if (error) - return; - break; - - case VMBUS_ICMSG_TYPE_HEARTBEAT: - /* Only ic_seq is a must */ - if (dlen < VMBUS_ICMSG_HEARTBEAT_SIZE_MIN) { - device_printf(sc->ic_dev, "invalid heartbeat len %d\n", - dlen); - return; - } - ((struct vmbus_icmsg_heartbeat *)data)->ic_seq++; - break; - - default: - device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); - break; - } - - /* - * Send response by echoing the request back. - */ - vmbus_ic_sendresp(sc, chan, data, dlen, xactid); -} - -static int -vmbus_heartbeat_probe(device_t dev) -{ - - return (vmbus_ic_probe(dev, vmbus_heartbeat_descs)); -} - -static int -vmbus_heartbeat_attach(device_t dev) -{ - - return (vmbus_ic_attach(dev, vmbus_heartbeat_cb)); -} Index: head/sys/dev/hyperv/utilities/hv_shutdown.c =================================================================== --- head/sys/dev/hyperv/utilities/hv_shutdown.c +++ head/sys/dev/hyperv/utilities/hv_shutdown.c @@ -1,167 +0,0 @@ -/*- - * Copyright (c) 2014,2016 Microsoft Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define VMBUS_SHUTDOWN_FWVER_MAJOR 3 -#define VMBUS_SHUTDOWN_FWVER \ - VMBUS_IC_VERSION(VMBUS_SHUTDOWN_FWVER_MAJOR, 0) - -#define VMBUS_SHUTDOWN_MSGVER_MAJOR 3 -#define VMBUS_SHUTDOWN_MSGVER \ - VMBUS_IC_VERSION(VMBUS_SHUTDOWN_MSGVER_MAJOR, 0) - -static int vmbus_shutdown_probe(device_t); -static int vmbus_shutdown_attach(device_t); - -static const struct vmbus_ic_desc vmbus_shutdown_descs[] = { - { - .ic_guid = { .hv_guid = { - 0x31, 0x60, 0x0b, 0x0e, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8b, 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb } }, - .ic_desc = "Hyper-V Shutdown" - }, - VMBUS_IC_DESC_END -}; - -static device_method_t vmbus_shutdown_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, vmbus_shutdown_probe), - DEVMETHOD(device_attach, vmbus_shutdown_attach), - DEVMETHOD(device_detach, vmbus_ic_detach), - DEVMETHOD_END -}; - -static driver_t vmbus_shutdown_driver = { - "hvshutdown", - vmbus_shutdown_methods, - sizeof(struct vmbus_ic_softc) -}; - -static devclass_t vmbus_shutdown_devclass; - -DRIVER_MODULE(hv_shutdown, vmbus, vmbus_shutdown_driver, - vmbus_shutdown_devclass, NULL, NULL); -MODULE_VERSION(hv_shutdown, 1); -MODULE_DEPEND(hv_shutdown, vmbus, 1, 1, 1); - -static void -vmbus_shutdown_cb(struct vmbus_channel *chan, void *xsc) -{ - struct vmbus_ic_softc *sc = xsc; - struct vmbus_icmsg_hdr *hdr; - struct vmbus_icmsg_shutdown *msg; - int dlen, error, do_shutdown = 0; - uint64_t xactid; - void *data; - - /* - * Receive request. - */ - data = sc->ic_buf; - dlen = sc->ic_buflen; - error = vmbus_chan_recv(chan, data, &dlen, &xactid); - KASSERT(error != ENOBUFS, ("icbuf is not large enough")); - if (error) - return; - - if (dlen < sizeof(*hdr)) { - device_printf(sc->ic_dev, "invalid data len %d\n", dlen); - return; - } - hdr = data; - - /* - * Update request, which will be echoed back as response. - */ - switch (hdr->ic_type) { - case VMBUS_ICMSG_TYPE_NEGOTIATE: - error = vmbus_ic_negomsg(sc, data, &dlen, - VMBUS_SHUTDOWN_FWVER, VMBUS_SHUTDOWN_MSGVER); - if (error) - return; - break; - - case VMBUS_ICMSG_TYPE_SHUTDOWN: - if (dlen < VMBUS_ICMSG_SHUTDOWN_SIZE_MIN) { - device_printf(sc->ic_dev, "invalid shutdown len %d\n", - dlen); - return; - } - msg = data; - - /* XXX ic_flags definition? */ - if (msg->ic_haltflags == 0 || msg->ic_haltflags == 1) { - device_printf(sc->ic_dev, "shutdown requested\n"); - hdr->ic_status = VMBUS_ICMSG_STATUS_OK; - do_shutdown = 1; - } else { - device_printf(sc->ic_dev, "unknown shutdown flags " - "0x%08x\n", msg->ic_haltflags); - hdr->ic_status = VMBUS_ICMSG_STATUS_FAIL; - } - break; - - default: - device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); - break; - } - - /* - * Send response by echoing the request back. - */ - vmbus_ic_sendresp(sc, chan, data, dlen, xactid); - - if (do_shutdown) - shutdown_nice(RB_POWEROFF); -} - -static int -vmbus_shutdown_probe(device_t dev) -{ - - return (vmbus_ic_probe(dev, vmbus_shutdown_descs)); -} - -static int -vmbus_shutdown_attach(device_t dev) -{ - - return (vmbus_ic_attach(dev, vmbus_shutdown_cb)); -} Index: head/sys/dev/hyperv/utilities/hv_timesync.c =================================================================== --- head/sys/dev/hyperv/utilities/hv_timesync.c +++ head/sys/dev/hyperv/utilities/hv_timesync.c @@ -1,245 +0,0 @@ -/*- - * Copyright (c) 2014,2016 Microsoft Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define VMBUS_TIMESYNC_FWVER_MAJOR 3 -#define VMBUS_TIMESYNC_FWVER \ - VMBUS_IC_VERSION(VMBUS_TIMESYNC_FWVER_MAJOR, 0) - -#define VMBUS_TIMESYNC_MSGVER_MAJOR 4 -#define VMBUS_TIMESYNC_MSGVER \ - VMBUS_IC_VERSION(VMBUS_TIMESYNC_MSGVER_MAJOR, 0) - -#define VMBUS_TIMESYNC_DORTT(sc) \ - ((sc)->ic_msgver >= VMBUS_IC_VERSION(4, 0) && \ - (hyperv_features & CPUID_HV_MSR_TIME_REFCNT)) - -static int vmbus_timesync_probe(device_t); -static int vmbus_timesync_attach(device_t); - -static const struct vmbus_ic_desc vmbus_timesync_descs[] = { - { - .ic_guid = { .hv_guid = { - 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf } }, - .ic_desc = "Hyper-V Timesync" - }, - VMBUS_IC_DESC_END -}; - -static device_method_t vmbus_timesync_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, vmbus_timesync_probe), - DEVMETHOD(device_attach, vmbus_timesync_attach), - DEVMETHOD(device_detach, vmbus_ic_detach), - DEVMETHOD_END -}; - -static driver_t vmbus_timesync_driver = { - "hvtimesync", - vmbus_timesync_methods, - sizeof(struct vmbus_ic_softc) -}; - -static devclass_t vmbus_timesync_devclass; - -DRIVER_MODULE(hv_timesync, vmbus, vmbus_timesync_driver, - vmbus_timesync_devclass, NULL, NULL); -MODULE_VERSION(hv_timesync, 1); -MODULE_DEPEND(hv_timesync, vmbus, 1, 1, 1); - -SYSCTL_NODE(_hw, OID_AUTO, hvtimesync, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, - "Hyper-V timesync interface"); - -static int vmbus_ts_ignore_sync = 0; -SYSCTL_INT(_hw_hvtimesync, OID_AUTO, ignore_sync, CTLFLAG_RWTUN, - &vmbus_ts_ignore_sync, 0, "Ignore the sync request."); - -/* - * Trigger sample sync when drift exceeds threshold (ms). - * Ignore the sample request when set to 0. - */ -static int vmbus_ts_sample_thresh = 100; -SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_thresh, CTLFLAG_RWTUN, - &vmbus_ts_sample_thresh, 0, - "Threshold that makes sample request trigger the sync (unit: ms)."); - -static int vmbus_ts_sample_verbose = 0; -SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_verbose, CTLFLAG_RWTUN, - &vmbus_ts_sample_verbose, 0, "Increase sample request verbosity."); - -static void -vmbus_timesync(struct vmbus_ic_softc *sc, uint64_t hvtime, uint64_t sent_tc, - uint8_t tsflags) -{ - struct timespec vm_ts; - uint64_t hv_ns, vm_ns, rtt = 0; - - if (VMBUS_TIMESYNC_DORTT(sc)) - rtt = rdmsr(MSR_HV_TIME_REF_COUNT) - sent_tc; - - hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE + rtt) * HYPERV_TIMER_NS_FACTOR; - nanotime(&vm_ts); - vm_ns = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec; - - if ((tsflags & VMBUS_ICMSG_TS_FLAG_SYNC) && !vmbus_ts_ignore_sync) { - struct timespec hv_ts; - - if (bootverbose) { - device_printf(sc->ic_dev, "apply sync request, " - "hv: %ju, vm: %ju\n", - (uintmax_t)hv_ns, (uintmax_t)vm_ns); - } - hv_ts.tv_sec = hv_ns / NANOSEC; - hv_ts.tv_nsec = hv_ns % NANOSEC; - kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts); - /* Done! */ - return; - } - - if ((tsflags & VMBUS_ICMSG_TS_FLAG_SAMPLE) && - vmbus_ts_sample_thresh > 0) { - int64_t diff; - - if (vmbus_ts_sample_verbose) { - device_printf(sc->ic_dev, "sample request, " - "hv: %ju, vm: %ju\n", - (uintmax_t)hv_ns, (uintmax_t)vm_ns); - } - - if (hv_ns > vm_ns) - diff = hv_ns - vm_ns; - else - diff = vm_ns - hv_ns; - /* nanosec -> millisec */ - diff /= 1000000; - - if (diff > vmbus_ts_sample_thresh) { - struct timespec hv_ts; - - if (bootverbose) { - device_printf(sc->ic_dev, - "apply sample request, hv: %ju, vm: %ju\n", - (uintmax_t)hv_ns, (uintmax_t)vm_ns); - } - hv_ts.tv_sec = hv_ns / NANOSEC; - hv_ts.tv_nsec = hv_ns % NANOSEC; - kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts); - } - /* Done */ - return; - } -} - -static void -vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc) -{ - struct vmbus_ic_softc *sc = xsc; - struct vmbus_icmsg_hdr *hdr; - const struct vmbus_icmsg_timesync *msg; - int dlen, error; - uint64_t xactid; - void *data; - - /* - * Receive request. - */ - data = sc->ic_buf; - dlen = sc->ic_buflen; - error = vmbus_chan_recv(chan, data, &dlen, &xactid); - KASSERT(error != ENOBUFS, ("icbuf is not large enough")); - if (error) - return; - - if (dlen < sizeof(*hdr)) { - device_printf(sc->ic_dev, "invalid data len %d\n", dlen); - return; - } - hdr = data; - - /* - * Update request, which will be echoed back as response. - */ - switch (hdr->ic_type) { - case VMBUS_ICMSG_TYPE_NEGOTIATE: - error = vmbus_ic_negomsg(sc, data, &dlen, - VMBUS_TIMESYNC_FWVER, VMBUS_TIMESYNC_MSGVER); - if (error) - return; - if (VMBUS_TIMESYNC_DORTT(sc)) - device_printf(sc->ic_dev, "RTT\n"); - break; - - case VMBUS_ICMSG_TYPE_TIMESYNC: - if (dlen < sizeof(*msg)) { - device_printf(sc->ic_dev, "invalid timesync len %d\n", - dlen); - return; - } - msg = data; - vmbus_timesync(sc, msg->ic_hvtime, msg->ic_sent_tc, - msg->ic_tsflags); - break; - - default: - device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); - break; - } - - /* - * Send response by echoing the request back. - */ - vmbus_ic_sendresp(sc, chan, data, dlen, xactid); -} - -static int -vmbus_timesync_probe(device_t dev) -{ - - return (vmbus_ic_probe(dev, vmbus_timesync_descs)); -} - -static int -vmbus_timesync_attach(device_t dev) -{ - - return (vmbus_ic_attach(dev, vmbus_timesync_cb)); -} Index: head/sys/dev/hyperv/utilities/vmbus_heartbeat.c =================================================================== --- head/sys/dev/hyperv/utilities/vmbus_heartbeat.c +++ head/sys/dev/hyperv/utilities/vmbus_heartbeat.c @@ -0,0 +1,152 @@ +/*- + * Copyright (c) 2014,2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VMBUS_HEARTBEAT_FWVER_MAJOR 3 +#define VMBUS_HEARTBEAT_FWVER \ + VMBUS_IC_VERSION(VMBUS_HEARTBEAT_FWVER_MAJOR, 0) + +#define VMBUS_HEARTBEAT_MSGVER_MAJOR 3 +#define VMBUS_HEARTBEAT_MSGVER \ + VMBUS_IC_VERSION(VMBUS_HEARTBEAT_MSGVER_MAJOR, 0) + +static int vmbus_heartbeat_probe(device_t); +static int vmbus_heartbeat_attach(device_t); + +static const struct vmbus_ic_desc vmbus_heartbeat_descs[] = { + { + .ic_guid = { .hv_guid = { + 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d} }, + .ic_desc = "Hyper-V Heartbeat" + }, + VMBUS_IC_DESC_END +}; + +static device_method_t vmbus_heartbeat_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vmbus_heartbeat_probe), + DEVMETHOD(device_attach, vmbus_heartbeat_attach), + DEVMETHOD(device_detach, vmbus_ic_detach), + DEVMETHOD_END +}; + +static driver_t vmbus_heartbeat_driver = { + "hvheartbeat", + vmbus_heartbeat_methods, + sizeof(struct vmbus_ic_softc) +}; + +static devclass_t vmbus_heartbeat_devclass; + +DRIVER_MODULE(hv_heartbeat, vmbus, vmbus_heartbeat_driver, + vmbus_heartbeat_devclass, NULL, NULL); +MODULE_VERSION(hv_heartbeat, 1); +MODULE_DEPEND(hv_heartbeat, vmbus, 1, 1, 1); + +static void +vmbus_heartbeat_cb(struct vmbus_channel *chan, void *xsc) +{ + struct vmbus_ic_softc *sc = xsc; + struct vmbus_icmsg_hdr *hdr; + int dlen, error; + uint64_t xactid; + void *data; + + /* + * Receive request. + */ + data = sc->ic_buf; + dlen = sc->ic_buflen; + error = vmbus_chan_recv(chan, data, &dlen, &xactid); + KASSERT(error != ENOBUFS, ("icbuf is not large enough")); + if (error) + return; + + if (dlen < sizeof(*hdr)) { + device_printf(sc->ic_dev, "invalid data len %d\n", dlen); + return; + } + hdr = data; + + /* + * Update request, which will be echoed back as response. + */ + switch (hdr->ic_type) { + case VMBUS_ICMSG_TYPE_NEGOTIATE: + error = vmbus_ic_negomsg(sc, data, &dlen, + VMBUS_HEARTBEAT_FWVER, VMBUS_HEARTBEAT_MSGVER); + if (error) + return; + break; + + case VMBUS_ICMSG_TYPE_HEARTBEAT: + /* Only ic_seq is a must */ + if (dlen < VMBUS_ICMSG_HEARTBEAT_SIZE_MIN) { + device_printf(sc->ic_dev, "invalid heartbeat len %d\n", + dlen); + return; + } + ((struct vmbus_icmsg_heartbeat *)data)->ic_seq++; + break; + + default: + device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); + break; + } + + /* + * Send response by echoing the request back. + */ + vmbus_ic_sendresp(sc, chan, data, dlen, xactid); +} + +static int +vmbus_heartbeat_probe(device_t dev) +{ + + return (vmbus_ic_probe(dev, vmbus_heartbeat_descs)); +} + +static int +vmbus_heartbeat_attach(device_t dev) +{ + + return (vmbus_ic_attach(dev, vmbus_heartbeat_cb)); +} Index: head/sys/dev/hyperv/utilities/vmbus_shutdown.c =================================================================== --- head/sys/dev/hyperv/utilities/vmbus_shutdown.c +++ head/sys/dev/hyperv/utilities/vmbus_shutdown.c @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 2014,2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VMBUS_SHUTDOWN_FWVER_MAJOR 3 +#define VMBUS_SHUTDOWN_FWVER \ + VMBUS_IC_VERSION(VMBUS_SHUTDOWN_FWVER_MAJOR, 0) + +#define VMBUS_SHUTDOWN_MSGVER_MAJOR 3 +#define VMBUS_SHUTDOWN_MSGVER \ + VMBUS_IC_VERSION(VMBUS_SHUTDOWN_MSGVER_MAJOR, 0) + +static int vmbus_shutdown_probe(device_t); +static int vmbus_shutdown_attach(device_t); + +static const struct vmbus_ic_desc vmbus_shutdown_descs[] = { + { + .ic_guid = { .hv_guid = { + 0x31, 0x60, 0x0b, 0x0e, 0x13, 0x52, 0x34, 0x49, + 0x81, 0x8b, 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb } }, + .ic_desc = "Hyper-V Shutdown" + }, + VMBUS_IC_DESC_END +}; + +static device_method_t vmbus_shutdown_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vmbus_shutdown_probe), + DEVMETHOD(device_attach, vmbus_shutdown_attach), + DEVMETHOD(device_detach, vmbus_ic_detach), + DEVMETHOD_END +}; + +static driver_t vmbus_shutdown_driver = { + "hvshutdown", + vmbus_shutdown_methods, + sizeof(struct vmbus_ic_softc) +}; + +static devclass_t vmbus_shutdown_devclass; + +DRIVER_MODULE(hv_shutdown, vmbus, vmbus_shutdown_driver, + vmbus_shutdown_devclass, NULL, NULL); +MODULE_VERSION(hv_shutdown, 1); +MODULE_DEPEND(hv_shutdown, vmbus, 1, 1, 1); + +static void +vmbus_shutdown_cb(struct vmbus_channel *chan, void *xsc) +{ + struct vmbus_ic_softc *sc = xsc; + struct vmbus_icmsg_hdr *hdr; + struct vmbus_icmsg_shutdown *msg; + int dlen, error, do_shutdown = 0; + uint64_t xactid; + void *data; + + /* + * Receive request. + */ + data = sc->ic_buf; + dlen = sc->ic_buflen; + error = vmbus_chan_recv(chan, data, &dlen, &xactid); + KASSERT(error != ENOBUFS, ("icbuf is not large enough")); + if (error) + return; + + if (dlen < sizeof(*hdr)) { + device_printf(sc->ic_dev, "invalid data len %d\n", dlen); + return; + } + hdr = data; + + /* + * Update request, which will be echoed back as response. + */ + switch (hdr->ic_type) { + case VMBUS_ICMSG_TYPE_NEGOTIATE: + error = vmbus_ic_negomsg(sc, data, &dlen, + VMBUS_SHUTDOWN_FWVER, VMBUS_SHUTDOWN_MSGVER); + if (error) + return; + break; + + case VMBUS_ICMSG_TYPE_SHUTDOWN: + if (dlen < VMBUS_ICMSG_SHUTDOWN_SIZE_MIN) { + device_printf(sc->ic_dev, "invalid shutdown len %d\n", + dlen); + return; + } + msg = data; + + /* XXX ic_flags definition? */ + if (msg->ic_haltflags == 0 || msg->ic_haltflags == 1) { + device_printf(sc->ic_dev, "shutdown requested\n"); + hdr->ic_status = VMBUS_ICMSG_STATUS_OK; + do_shutdown = 1; + } else { + device_printf(sc->ic_dev, "unknown shutdown flags " + "0x%08x\n", msg->ic_haltflags); + hdr->ic_status = VMBUS_ICMSG_STATUS_FAIL; + } + break; + + default: + device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); + break; + } + + /* + * Send response by echoing the request back. + */ + vmbus_ic_sendresp(sc, chan, data, dlen, xactid); + + if (do_shutdown) + shutdown_nice(RB_POWEROFF); +} + +static int +vmbus_shutdown_probe(device_t dev) +{ + + return (vmbus_ic_probe(dev, vmbus_shutdown_descs)); +} + +static int +vmbus_shutdown_attach(device_t dev) +{ + + return (vmbus_ic_attach(dev, vmbus_shutdown_cb)); +} Index: head/sys/dev/hyperv/utilities/vmbus_timesync.c =================================================================== --- head/sys/dev/hyperv/utilities/vmbus_timesync.c +++ head/sys/dev/hyperv/utilities/vmbus_timesync.c @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 2014,2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VMBUS_TIMESYNC_FWVER_MAJOR 3 +#define VMBUS_TIMESYNC_FWVER \ + VMBUS_IC_VERSION(VMBUS_TIMESYNC_FWVER_MAJOR, 0) + +#define VMBUS_TIMESYNC_MSGVER_MAJOR 4 +#define VMBUS_TIMESYNC_MSGVER \ + VMBUS_IC_VERSION(VMBUS_TIMESYNC_MSGVER_MAJOR, 0) + +#define VMBUS_TIMESYNC_DORTT(sc) \ + ((sc)->ic_msgver >= VMBUS_IC_VERSION(4, 0) && \ + (hyperv_features & CPUID_HV_MSR_TIME_REFCNT)) + +static int vmbus_timesync_probe(device_t); +static int vmbus_timesync_attach(device_t); + +static const struct vmbus_ic_desc vmbus_timesync_descs[] = { + { + .ic_guid = { .hv_guid = { + 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, + 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf } }, + .ic_desc = "Hyper-V Timesync" + }, + VMBUS_IC_DESC_END +}; + +static device_method_t vmbus_timesync_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vmbus_timesync_probe), + DEVMETHOD(device_attach, vmbus_timesync_attach), + DEVMETHOD(device_detach, vmbus_ic_detach), + DEVMETHOD_END +}; + +static driver_t vmbus_timesync_driver = { + "hvtimesync", + vmbus_timesync_methods, + sizeof(struct vmbus_ic_softc) +}; + +static devclass_t vmbus_timesync_devclass; + +DRIVER_MODULE(hv_timesync, vmbus, vmbus_timesync_driver, + vmbus_timesync_devclass, NULL, NULL); +MODULE_VERSION(hv_timesync, 1); +MODULE_DEPEND(hv_timesync, vmbus, 1, 1, 1); + +SYSCTL_NODE(_hw, OID_AUTO, hvtimesync, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, + "Hyper-V timesync interface"); + +static int vmbus_ts_ignore_sync = 0; +SYSCTL_INT(_hw_hvtimesync, OID_AUTO, ignore_sync, CTLFLAG_RWTUN, + &vmbus_ts_ignore_sync, 0, "Ignore the sync request."); + +/* + * Trigger sample sync when drift exceeds threshold (ms). + * Ignore the sample request when set to 0. + */ +static int vmbus_ts_sample_thresh = 100; +SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_thresh, CTLFLAG_RWTUN, + &vmbus_ts_sample_thresh, 0, + "Threshold that makes sample request trigger the sync (unit: ms)."); + +static int vmbus_ts_sample_verbose = 0; +SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_verbose, CTLFLAG_RWTUN, + &vmbus_ts_sample_verbose, 0, "Increase sample request verbosity."); + +static void +vmbus_timesync(struct vmbus_ic_softc *sc, uint64_t hvtime, uint64_t sent_tc, + uint8_t tsflags) +{ + struct timespec vm_ts; + uint64_t hv_ns, vm_ns, rtt = 0; + + if (VMBUS_TIMESYNC_DORTT(sc)) + rtt = rdmsr(MSR_HV_TIME_REF_COUNT) - sent_tc; + + hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE + rtt) * HYPERV_TIMER_NS_FACTOR; + nanotime(&vm_ts); + vm_ns = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec; + + if ((tsflags & VMBUS_ICMSG_TS_FLAG_SYNC) && !vmbus_ts_ignore_sync) { + struct timespec hv_ts; + + if (bootverbose) { + device_printf(sc->ic_dev, "apply sync request, " + "hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); + } + hv_ts.tv_sec = hv_ns / NANOSEC; + hv_ts.tv_nsec = hv_ns % NANOSEC; + kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts); + /* Done! */ + return; + } + + if ((tsflags & VMBUS_ICMSG_TS_FLAG_SAMPLE) && + vmbus_ts_sample_thresh > 0) { + int64_t diff; + + if (vmbus_ts_sample_verbose) { + device_printf(sc->ic_dev, "sample request, " + "hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); + } + + if (hv_ns > vm_ns) + diff = hv_ns - vm_ns; + else + diff = vm_ns - hv_ns; + /* nanosec -> millisec */ + diff /= 1000000; + + if (diff > vmbus_ts_sample_thresh) { + struct timespec hv_ts; + + if (bootverbose) { + device_printf(sc->ic_dev, + "apply sample request, hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); + } + hv_ts.tv_sec = hv_ns / NANOSEC; + hv_ts.tv_nsec = hv_ns % NANOSEC; + kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts); + } + /* Done */ + return; + } +} + +static void +vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc) +{ + struct vmbus_ic_softc *sc = xsc; + struct vmbus_icmsg_hdr *hdr; + const struct vmbus_icmsg_timesync *msg; + int dlen, error; + uint64_t xactid; + void *data; + + /* + * Receive request. + */ + data = sc->ic_buf; + dlen = sc->ic_buflen; + error = vmbus_chan_recv(chan, data, &dlen, &xactid); + KASSERT(error != ENOBUFS, ("icbuf is not large enough")); + if (error) + return; + + if (dlen < sizeof(*hdr)) { + device_printf(sc->ic_dev, "invalid data len %d\n", dlen); + return; + } + hdr = data; + + /* + * Update request, which will be echoed back as response. + */ + switch (hdr->ic_type) { + case VMBUS_ICMSG_TYPE_NEGOTIATE: + error = vmbus_ic_negomsg(sc, data, &dlen, + VMBUS_TIMESYNC_FWVER, VMBUS_TIMESYNC_MSGVER); + if (error) + return; + if (VMBUS_TIMESYNC_DORTT(sc)) + device_printf(sc->ic_dev, "RTT\n"); + break; + + case VMBUS_ICMSG_TYPE_TIMESYNC: + if (dlen < sizeof(*msg)) { + device_printf(sc->ic_dev, "invalid timesync len %d\n", + dlen); + return; + } + msg = data; + vmbus_timesync(sc, msg->ic_hvtime, msg->ic_sent_tc, + msg->ic_tsflags); + break; + + default: + device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); + break; + } + + /* + * Send response by echoing the request back. + */ + vmbus_ic_sendresp(sc, chan, data, dlen, xactid); +} + +static int +vmbus_timesync_probe(device_t dev) +{ + + return (vmbus_ic_probe(dev, vmbus_timesync_descs)); +} + +static int +vmbus_timesync_attach(device_t dev) +{ + + return (vmbus_ic_attach(dev, vmbus_timesync_cb)); +} Index: head/sys/modules/hyperv/utilities/Makefile =================================================================== --- head/sys/modules/hyperv/utilities/Makefile +++ head/sys/modules/hyperv/utilities/Makefile @@ -4,11 +4,11 @@ KMOD= hv_utils SRCS= vmbus_ic.c -SRCS+= hv_heartbeat.c SRCS+= hv_kvp.c -SRCS+= hv_shutdown.c SRCS+= hv_snapshot.c -SRCS+= hv_timesync.c +SRCS+= vmbus_heartbeat.c +SRCS+= vmbus_shutdown.c +SRCS+= vmbus_timesync.c SRCS+= bus_if.h device_if.h vmbus_if.h CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \