Index: stable/11/sys/dev/hyperv/utilities/hv_heartbeat.c =================================================================== --- stable/11/sys/dev/hyperv/utilities/hv_heartbeat.c (revision 307496) +++ stable/11/sys/dev/hyperv/utilities/hv_heartbeat.c (revision 307497) @@ -1,141 +1,141 @@ /*- * 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 "vmbus_if.h" 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 void vmbus_heartbeat_cb(struct vmbus_channel *chan, void *xsc) { struct hv_util_sc *sc = xsc; struct vmbus_icmsg_hdr *hdr; int dlen, error; uint64_t xactid; void *data; /* * Receive request. */ data = sc->receive_buffer; 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(struct vmbus_icmsg_hdr)) { + 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); 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 updated request back. */ hdr->ic_flags = VMBUS_ICMSG_FLAG_XACT | VMBUS_ICMSG_FLAG_RESP; error = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, 0, data, dlen, xactid); if (error) device_printf(sc->ic_dev, "resp send failed: %d\n", error); } static int hv_heartbeat_probe(device_t dev) { return (vmbus_ic_probe(dev, vmbus_heartbeat_descs)); } static int hv_heartbeat_attach(device_t dev) { return (hv_util_attach(dev, vmbus_heartbeat_cb)); } static device_method_t heartbeat_methods[] = { /* Device interface */ DEVMETHOD(device_probe, hv_heartbeat_probe), DEVMETHOD(device_attach, hv_heartbeat_attach), DEVMETHOD(device_detach, hv_util_detach), { 0, 0 } }; static driver_t heartbeat_driver = { "hvheartbeat", heartbeat_methods, sizeof(hv_util_sc)}; static devclass_t heartbeat_devclass; DRIVER_MODULE(hv_heartbeat, vmbus, heartbeat_driver, heartbeat_devclass, NULL, NULL); MODULE_VERSION(hv_heartbeat, 1); MODULE_DEPEND(hv_heartbeat, vmbus, 1, 1, 1); Index: stable/11/sys/dev/hyperv/utilities/hv_shutdown.c =================================================================== --- stable/11/sys/dev/hyperv/utilities/hv_shutdown.c (revision 307496) +++ stable/11/sys/dev/hyperv/utilities/hv_shutdown.c (revision 307497) @@ -1,155 +1,156 @@ /*- * 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. - * - * $FreeBSD$ */ -/* - * A common driver for all hyper-V util services. - */ +#include +__FBSDID("$FreeBSD$"); #include -#include #include -#include +#include #include #include -#include -#include #include #include #include -#include -#include "hv_util.h" +#include +#include + #include "vmbus_if.h" 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 }; -/** - * Shutdown - */ static void -hv_shutdown_cb(struct vmbus_channel *channel, void *context) +vmbus_shutdown_cb(struct vmbus_channel *chan, void *xsc) { - uint8_t* buf; - uint8_t execute_shutdown = 0; - hv_vmbus_icmsg_hdr* icmsghdrp; - uint32_t recv_len; - uint64_t request_id; - int ret; - hv_vmbus_shutdown_msg_data* shutdown_msg; - hv_util_sc *softc; + struct hv_util_sc *sc = xsc; + struct vmbus_icmsg_hdr *hdr; + struct vmbus_icmsg_shutdown *msg; + int dlen, error, do_shutdown = 0; + uint64_t xactid; + void *data; - softc = (hv_util_sc*)context; - buf = softc->receive_buffer; + /* + * Receive request. + */ + data = sc->receive_buffer; + dlen = sc->ic_buflen; + error = vmbus_chan_recv(chan, data, &dlen, &xactid); + KASSERT(error != ENOBUFS, ("icbuf is not large enough")); + if (error) + return; - recv_len = softc->ic_buflen; - ret = vmbus_chan_recv(channel, buf, &recv_len, &request_id); - KASSERT(ret != ENOBUFS, ("hvshutdown recvbuf is not large enough")); - /* XXX check recv_len to make sure that it contains enough data */ + if (dlen < sizeof(*hdr)) { + device_printf(sc->ic_dev, "invalid data len %d\n", dlen); + return; + } + hdr = data; - if ((ret == 0) && recv_len > 0) { - - icmsghdrp = (struct hv_vmbus_icmsg_hdr *) - &buf[sizeof(struct hv_vmbus_pipe_hdr)]; - - if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { - int error; - - error = vmbus_ic_negomsg(softc, buf, &recv_len); + /* + * 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); if (error) return; - } else { - shutdown_msg = - (struct hv_vmbus_shutdown_msg_data *) - &buf[sizeof(struct hv_vmbus_pipe_hdr) + - sizeof(struct hv_vmbus_icmsg_hdr)]; + break; - switch (shutdown_msg->flags) { - case 0: - case 1: - icmsghdrp->status = HV_S_OK; - execute_shutdown = 1; - if(bootverbose) - printf("Shutdown request received -" - " graceful shutdown initiated\n"); - break; - default: - icmsghdrp->status = HV_E_FAIL; - execute_shutdown = 0; - printf("Shutdown request received -" - " Invalid request\n"); - 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; - icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | - HV_ICMSGHDRFLAG_RESPONSE; + /* 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; - vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, - buf, recv_len, request_id); + default: + device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); + break; } - if (execute_shutdown) - shutdown_nice(RB_POWEROFF); + /* + * Send response by echoing the updated request back. + */ + hdr->ic_flags = VMBUS_ICMSG_FLAG_XACT | VMBUS_ICMSG_FLAG_RESP; + error = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, 0, + data, dlen, xactid); + if (error) + device_printf(sc->ic_dev, "resp send failed: %d\n", error); + + if (do_shutdown) + shutdown_nice(RB_POWEROFF); } static int hv_shutdown_probe(device_t dev) { return (vmbus_ic_probe(dev, vmbus_shutdown_descs)); } static int hv_shutdown_attach(device_t dev) { - return hv_util_attach(dev, hv_shutdown_cb); + + return (hv_util_attach(dev, vmbus_shutdown_cb)); } static device_method_t shutdown_methods[] = { /* Device interface */ DEVMETHOD(device_probe, hv_shutdown_probe), DEVMETHOD(device_attach, hv_shutdown_attach), DEVMETHOD(device_detach, hv_util_detach), { 0, 0 } }; static driver_t shutdown_driver = { "hvshutdown", shutdown_methods, sizeof(hv_util_sc)}; static devclass_t shutdown_devclass; DRIVER_MODULE(hv_shutdown, vmbus, shutdown_driver, shutdown_devclass, NULL, NULL); MODULE_VERSION(hv_shutdown, 1); MODULE_DEPEND(hv_shutdown, vmbus, 1, 1, 1); Index: stable/11/sys/dev/hyperv/utilities/hv_timesync.c =================================================================== --- stable/11/sys/dev/hyperv/utilities/hv_timesync.c (revision 307496) +++ stable/11/sys/dev/hyperv/utilities/hv_timesync.c (revision 307497) @@ -1,231 +1,223 @@ /*- * 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. - * - * $FreeBSD$ */ -/* - * A common driver for all hyper-V util services. - */ +#include +__FBSDID("$FreeBSD$"); #include -#include #include -#include +#include #include -#include -#include #include -#include #include +#include #include #include -#include -#include "hv_util.h" +#include +#include + #include "vmbus_if.h" -#define HV_WLTIMEDELTA 116444736000000000L /* in 100ns unit */ -#define HV_ICTIMESYNCFLAG_PROBE 0 -#define HV_ICTIMESYNCFLAG_SYNC 1 -#define HV_ICTIMESYNCFLAG_SAMPLE 2 -#define HV_NANO_SEC_PER_SEC 1000000000 -#define HV_NANO_SEC_PER_MILLI_SEC 1000000 - 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 }; -struct hv_ictimesync_data { - uint64_t parenttime; - uint64_t childtime; - uint64_t roundtriptime; - uint8_t flags; -} __packed; - -/* - * Globals - */ SYSCTL_NODE(_hw, OID_AUTO, hvtimesync, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, "Hyper-V timesync interface"); -/* Ignore the sync request when set to 1. */ -static int ignore_sync_req = 0; -SYSCTL_INT(_hw_hvtimesync, OID_AUTO, ignore_sync_req, CTLFLAG_RWTUN, - &ignore_sync_req, 0, - "Ignore the sync request when set to 1."); +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 sample_drift = 100; -SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_drift, CTLFLAG_RWTUN, - &sample_drift, 0, - "Threshold that makes sample request trigger the sync."); +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)."); -/** - * @brief Synchronize time with host after reboot, restore, etc. - * - * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM. - * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time - * message after the timesync channel is opened. Since the hv_utils module is - * loaded after hv_vmbus, the first message is usually missed. The other - * thing is, systime is automatically set to emulated hardware clock which may - * not be UTC time or in the same time zone. So, to override these effects, we - * use the first 50 time samples for initial system time setting. - */ -static inline -void hv_adj_guesttime(hv_util_sc *sc, uint64_t hosttime, uint8_t flags) +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 hv_util_sc *sc, uint64_t hvtime, uint8_t tsflags) { - struct timespec guest_ts, host_ts; - uint64_t host_tns, guest_tns; - int64_t diff; - int error; + struct timespec vm_ts; + uint64_t hv_ns, vm_ns; - host_tns = (hosttime - HV_WLTIMEDELTA) * 100; - host_ts.tv_sec = (time_t)(host_tns/HV_NANO_SEC_PER_SEC); - host_ts.tv_nsec = (long)(host_tns%HV_NANO_SEC_PER_SEC); + hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE) * VMBUS_ICMSG_TS_FACTOR; + nanotime(&vm_ts); + vm_ns = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec; - nanotime(&guest_ts); - guest_tns = guest_ts.tv_sec * HV_NANO_SEC_PER_SEC + guest_ts.tv_nsec; + if ((tsflags & VMBUS_ICMSG_TS_FLAG_SYNC) && !vmbus_ts_ignore_sync) { + struct timespec hv_ts; - if ((flags & HV_ICTIMESYNCFLAG_SYNC) != 0 && ignore_sync_req == 0) { if (bootverbose) { - device_printf(sc->ic_dev, "handle sync request " - "{host: %ju, guest: %ju}\n", - (uintmax_t)host_tns, (uintmax_t)guest_tns); + device_printf(sc->ic_dev, "apply sync request, " + "hv: %ju, vm: %ju\n", + (uintmax_t)hv_ns, (uintmax_t)vm_ns); } - - error = kern_clock_settime(curthread, CLOCK_REALTIME, - &host_ts); + 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 ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0 && sample_drift != 0) { - if (bootverbose) { - device_printf(sc->ic_dev, "handle sample request " - "{host: %ju, guest: %ju}\n", - (uintmax_t)host_tns, (uintmax_t)guest_tns); + 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); } - diff = (int64_t)(host_tns - guest_tns) / HV_NANO_SEC_PER_MILLI_SEC; - if (diff > sample_drift || diff < -sample_drift) { - error = kern_clock_settime(curthread, CLOCK_REALTIME, - &host_ts); - if (bootverbose) - device_printf(sc->ic_dev, "trigger sample sync"); + 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; } } -/** - * Time Sync Channel message handler - */ static void -hv_timesync_cb(struct vmbus_channel *channel, void *context) +vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc) { - hv_vmbus_icmsg_hdr* icmsghdrp; - uint32_t recvlen; - uint64_t requestId; - int ret; - uint8_t* time_buf; - struct hv_ictimesync_data* timedatap; - hv_util_sc *softc; + struct hv_util_sc *sc = xsc; + struct vmbus_icmsg_hdr *hdr; + const struct vmbus_icmsg_timesync *msg; + int dlen, error; + uint64_t xactid; + void *data; - softc = (hv_util_sc*)context; - time_buf = softc->receive_buffer; + /* + * Receive request. + */ + data = sc->receive_buffer; + dlen = sc->ic_buflen; + error = vmbus_chan_recv(chan, data, &dlen, &xactid); + KASSERT(error != ENOBUFS, ("icbuf is not large enough")); + if (error) + return; - recvlen = softc->ic_buflen; - ret = vmbus_chan_recv(channel, time_buf, &recvlen, &requestId); - KASSERT(ret != ENOBUFS, ("hvtimesync recvbuf is not large enough")); - /* XXX check recvlen to make sure that it contains enough data */ + if (dlen < sizeof(*hdr)) { + device_printf(sc->ic_dev, "invalid data len %d\n", dlen); + return; + } + hdr = data; - if ((ret == 0) && recvlen > 0) { - icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &time_buf[ - sizeof(struct hv_vmbus_pipe_hdr)]; - - if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { - int error; - - error = vmbus_ic_negomsg(softc, time_buf, &recvlen); + /* + * 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); if (error) return; - } else { - timedatap = (struct hv_ictimesync_data *) &time_buf[ - sizeof(struct hv_vmbus_pipe_hdr) + - sizeof(struct hv_vmbus_icmsg_hdr)]; - hv_adj_guesttime(softc, timedatap->parenttime, timedatap->flags); - } + break; - icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION - | HV_ICMSGHDRFLAG_RESPONSE; + 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_tsflags); + break; - vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, - time_buf, recvlen, requestId); + default: + device_printf(sc->ic_dev, "got 0x%08x icmsg\n", hdr->ic_type); + break; } + + /* + * Send response by echoing the updated request back. + */ + hdr->ic_flags = VMBUS_ICMSG_FLAG_XACT | VMBUS_ICMSG_FLAG_RESP; + error = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_INBAND, 0, + data, dlen, xactid); + if (error) + device_printf(sc->ic_dev, "resp send failed: %d\n", error); } static int hv_timesync_probe(device_t dev) { return (vmbus_ic_probe(dev, vmbus_timesync_descs)); } static int hv_timesync_attach(device_t dev) { - return hv_util_attach(dev, hv_timesync_cb); -} -static int -hv_timesync_detach(device_t dev) -{ - return hv_util_detach(dev); + return (hv_util_attach(dev, vmbus_timesync_cb)); } static device_method_t timesync_methods[] = { /* Device interface */ DEVMETHOD(device_probe, hv_timesync_probe), DEVMETHOD(device_attach, hv_timesync_attach), - DEVMETHOD(device_detach, hv_timesync_detach), + DEVMETHOD(device_detach, hv_util_detach), { 0, 0 } }; static driver_t timesync_driver = { "hvtimesync", timesync_methods, sizeof(hv_util_sc)}; static devclass_t timesync_devclass; DRIVER_MODULE(hv_timesync, vmbus, timesync_driver, timesync_devclass, NULL, NULL); MODULE_VERSION(hv_timesync, 1); MODULE_DEPEND(hv_timesync, vmbus, 1, 1, 1); Index: stable/11/sys/dev/hyperv/utilities/vmbus_icreg.h =================================================================== --- stable/11/sys/dev/hyperv/utilities/vmbus_icreg.h (revision 307496) +++ stable/11/sys/dev/hyperv/utilities/vmbus_icreg.h (revision 307497) @@ -1,94 +1,125 @@ /*- * Copyright (c) 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. * * $FreeBSD$ */ #ifndef _VMBUS_ICREG_H_ #define _VMBUS_ICREG_H_ #define VMBUS_ICMSG_TYPE_NEGOTIATE 0 #define VMBUS_ICMSG_TYPE_HEARTBEAT 1 #define VMBUS_ICMSG_TYPE_KVP 2 #define VMBUS_ICMSG_TYPE_SHUTDOWN 3 #define VMBUS_ICMSG_TYPE_TIMESYNC 4 #define VMBUS_ICMSG_TYPE_VSS 5 #define VMBUS_ICMSG_STATUS_OK 0x00000000 #define VMBUS_ICMSG_STATUS_FAIL 0x80004005 #define VMBUS_IC_VERSION(major, minor) ((major) | (((uint32_t)(minor)) << 16)) #define VMBUS_ICVER_MAJOR(ver) ((ver) & 0xffff) #define VMBUS_ICVER_MINOR(ver) (((ver) & 0xffff0000) >> 16) struct vmbus_pipe_hdr { uint32_t ph_flags; uint32_t ph_msgsz; } __packed; struct vmbus_icmsg_hdr { struct vmbus_pipe_hdr ic_pipe; uint32_t ic_fwver; /* framework version */ uint16_t ic_type; uint32_t ic_msgver; /* message version */ uint16_t ic_dsize; /* data size */ uint32_t ic_status; /* VMBUS_ICMSG_STATUS_ */ uint8_t ic_xactid; uint8_t ic_flags; /* VMBUS_ICMSG_FLAG_ */ uint8_t ic_rsvd[2]; } __packed; #define VMBUS_ICMSG_FLAG_XACT 0x0001 #define VMBUS_ICMSG_FLAG_REQ 0x0002 #define VMBUS_ICMSG_FLAG_RESP 0x0004 /* VMBUS_ICMSG_TYPE_NEGOTIATE */ struct vmbus_icmsg_negotiate { struct vmbus_icmsg_hdr ic_hdr; uint16_t ic_fwver_cnt; uint16_t ic_msgver_cnt; uint32_t ic_rsvd; /* * This version array contains two set of supported * versions: * - The first set consists of #ic_fwver_cnt supported framework * versions. * - The second set consists of #ic_msgver_cnt supported message * versions. */ uint32_t ic_ver[]; } __packed; /* VMBUS_ICMSG_TYPE_HEARTBEAT */ struct vmbus_icmsg_heartbeat { struct vmbus_icmsg_hdr ic_hdr; uint64_t ic_seq; uint32_t ic_rsvd[8]; } __packed; #define VMBUS_ICMSG_HEARTBEAT_SIZE_MIN \ __offsetof(struct vmbus_icmsg_heartbeat, ic_rsvd[0]) +/* VMBUS_ICMSG_TYPE_SHUTDOWN */ +struct vmbus_icmsg_shutdown { + struct vmbus_icmsg_hdr ic_hdr; + uint32_t ic_code; + uint32_t ic_timeo; + uint32_t ic_haltflags; + uint8_t ic_msg[2048]; +} __packed; + +#define VMBUS_ICMSG_SHUTDOWN_SIZE_MIN \ + __offsetof(struct vmbus_icmsg_shutdown, ic_msg[0]) + +/* VMBUS_ICMSG_TYPE_TIMESYNC */ +struct vmbus_icmsg_timesync { + struct vmbus_icmsg_hdr ic_hdr; + uint64_t ic_hvtime; + uint64_t ic_vmtime; + uint64_t ic_rtt; + uint8_t ic_tsflags; /* VMBUS_ICMSG_TS_FLAG_ */ +} __packed; + +#define VMBUS_ICMSG_TS_FLAG_SYNC 0x01 +#define VMBUS_ICMSG_TS_FLAG_SAMPLE 0x02 + +/* XXX consolidate w/ hyperv */ +#define VMBUS_ICMSG_TS_BASE 116444736000000000ULL +#define VMBUS_ICMSG_TS_FACTOR 100ULL +#ifndef NANOSEC +#define NANOSEC 1000000000ULL +#endif + #endif /* !_VMBUS_ICREG_H_ */ Index: stable/11 =================================================================== --- stable/11 (revision 307496) +++ stable/11 (revision 307497) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r305279-305281