Index: head/sys/dev/hyperv/utilities/hv_heartbeat.c =================================================================== --- head/sys/dev/hyperv/utilities/hv_heartbeat.c (revision 304785) +++ head/sys/dev/hyperv/utilities/hv_heartbeat.c (revision 304786) @@ -1,132 +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. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #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_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 }; -/** - * Process heartbeat message - */ static void -hv_heartbeat_cb(struct vmbus_channel *channel, void *context) +vmbus_heartbeat_cb(struct vmbus_channel *chan, void *xsc) { - uint8_t* buf; - int recvlen; - uint64_t requestid; - int ret; + struct hv_util_sc *sc = xsc; + struct vmbus_icmsg_hdr *hdr; + int dlen, error; + uint64_t xactid; + void *data; - struct hv_vmbus_heartbeat_msg_data* heartbeat_msg; - struct hv_vmbus_icmsg_hdr* icmsghdrp; - hv_util_sc *softc; + /* + * 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; - softc = (hv_util_sc*)context; - buf = softc->receive_buffer; + if (dlen < sizeof(struct vmbus_icmsg_hdr)) { + device_printf(sc->ic_dev, "invalid data len %d\n", dlen); + return; + } + hdr = data; - recvlen = softc->ic_buflen; - ret = vmbus_chan_recv(channel, buf, &recvlen, &requestid); - KASSERT(ret != ENOBUFS, ("hvheartbeat recvbuf is not large enough")); - /* XXX check recvlen to make sure that it contains enough data */ - - if ((ret == 0) && recvlen > 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, 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 { - heartbeat_msg = - (struct hv_vmbus_heartbeat_msg_data *) - &buf[sizeof(struct hv_vmbus_pipe_hdr) + - sizeof(struct hv_vmbus_icmsg_hdr)]; + break; - heartbeat_msg->seq_num += 1; - } + 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; - icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | - HV_ICMSGHDRFLAG_RESPONSE; - - vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, - 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_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, hv_heartbeat_cb); + + 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: head/sys/dev/hyperv/utilities/vmbus_icreg.h =================================================================== --- head/sys/dev/hyperv/utilities/vmbus_icreg.h (revision 304785) +++ head/sys/dev/hyperv/utilities/vmbus_icreg.h (revision 304786) @@ -1,84 +1,94 @@ /*- * 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]) + #endif /* !_VMBUS_ICREG_H_ */