vmbus_heartbeat.c revision 303067
1295958Ssephe/*- 2298446Ssephe * Copyright (c) 2014,2016 Microsoft Corp. 3295958Ssephe * All rights reserved. 4295958Ssephe * 5295958Ssephe * Redistribution and use in source and binary forms, with or without 6295958Ssephe * modification, are permitted provided that the following conditions 7295958Ssephe * are met: 8295958Ssephe * 1. Redistributions of source code must retain the above copyright 9295958Ssephe * notice unmodified, this list of conditions, and the following 10295958Ssephe * disclaimer. 11295958Ssephe * 2. Redistributions in binary form must reproduce the above copyright 12295958Ssephe * notice, this list of conditions and the following disclaimer in the 13295958Ssephe * documentation and/or other materials provided with the distribution. 14295958Ssephe * 15295958Ssephe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16295958Ssephe * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17295958Ssephe * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18295958Ssephe * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19295958Ssephe * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20295958Ssephe * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21295958Ssephe * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22295958Ssephe * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23295958Ssephe * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24295958Ssephe * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25295958Ssephe * 26295958Ssephe * $FreeBSD: head/sys/dev/hyperv/utilities/hv_heartbeat.c 303067 2016-07-20 05:16:23Z sephe $ 27295958Ssephe */ 28295958Ssephe 29295958Ssephe#include <sys/param.h> 30295958Ssephe#include <sys/kernel.h> 31295958Ssephe#include <sys/bus.h> 32295958Ssephe#include <sys/malloc.h> 33295958Ssephe#include <sys/module.h> 34295958Ssephe#include <sys/timetc.h> 35295958Ssephe#include <sys/syscallsubr.h> 36295958Ssephe 37295958Ssephe#include <dev/hyperv/include/hyperv.h> 38302880Ssephe#include <dev/hyperv/include/vmbus.h> 39303067Ssephe#include <dev/hyperv/utilities/hv_utilreg.h> 40295958Ssephe#include "hv_util.h" 41302698Ssephe#include "vmbus_if.h" 42295958Ssephe 43295958Ssephe/* Heartbeat Service */ 44302802Ssephestatic const struct hyperv_guid service_guid = { .hv_guid = 45295958Ssephe {0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, 46295958Ssephe 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d} }; 47295958Ssephe 48295958Ssephe/** 49295958Ssephe * Process heartbeat message 50295958Ssephe */ 51295958Ssephestatic void 52295958Ssephehv_heartbeat_cb(void *context) 53295958Ssephe{ 54295958Ssephe uint8_t* buf; 55295958Ssephe hv_vmbus_channel* channel; 56302885Ssephe int recvlen; 57295958Ssephe uint64_t requestid; 58295958Ssephe int ret; 59295958Ssephe 60295958Ssephe struct hv_vmbus_heartbeat_msg_data* heartbeat_msg; 61295958Ssephe struct hv_vmbus_icmsg_hdr* icmsghdrp; 62295958Ssephe hv_util_sc *softc; 63295958Ssephe 64295958Ssephe softc = (hv_util_sc*)context; 65297793Spfg buf = softc->receive_buffer; 66302702Ssephe channel = softc->channel; 67295958Ssephe 68302885Ssephe recvlen = PAGE_SIZE; 69302885Ssephe ret = vmbus_chan_recv(channel, buf, &recvlen, &requestid); 70302885Ssephe KASSERT(ret != ENOBUFS, ("hvheartbeat recvbuf is not large enough")); 71302885Ssephe /* XXX check recvlen to make sure that it contains enough data */ 72295958Ssephe 73295958Ssephe if ((ret == 0) && recvlen > 0) { 74295958Ssephe 75295958Ssephe icmsghdrp = (struct hv_vmbus_icmsg_hdr *) 76295958Ssephe &buf[sizeof(struct hv_vmbus_pipe_hdr)]; 77295958Ssephe 78295958Ssephe if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { 79295958Ssephe hv_negotiate_version(icmsghdrp, NULL, buf); 80295958Ssephe 81295958Ssephe } else { 82295958Ssephe heartbeat_msg = 83295958Ssephe (struct hv_vmbus_heartbeat_msg_data *) 84295958Ssephe &buf[sizeof(struct hv_vmbus_pipe_hdr) + 85295958Ssephe sizeof(struct hv_vmbus_icmsg_hdr)]; 86295958Ssephe 87295958Ssephe heartbeat_msg->seq_num += 1; 88295958Ssephe } 89295958Ssephe 90295958Ssephe icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | 91295958Ssephe HV_ICMSGHDRFLAG_RESPONSE; 92295958Ssephe 93302882Ssephe vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, 94302882Ssephe buf, recvlen, requestid); 95295958Ssephe } 96295958Ssephe} 97295958Ssephe 98295958Ssephestatic int 99295958Ssephehv_heartbeat_probe(device_t dev) 100295958Ssephe{ 101297220Ssephe if (resource_disabled("hvheartbeat", 0)) 102297220Ssephe return ENXIO; 103297220Ssephe 104302698Ssephe if (VMBUS_PROBE_GUID(device_get_parent(dev), dev, &service_guid) == 0) { 105295958Ssephe device_set_desc(dev, "Hyper-V Heartbeat Service"); 106295958Ssephe return BUS_PROBE_DEFAULT; 107295958Ssephe } 108295958Ssephe return ENXIO; 109295958Ssephe} 110295958Ssephe 111295958Ssephestatic int 112295958Ssephehv_heartbeat_attach(device_t dev) 113295958Ssephe{ 114295958Ssephe hv_util_sc *softc = (hv_util_sc*)device_get_softc(dev); 115295958Ssephe 116295958Ssephe softc->callback = hv_heartbeat_cb; 117295958Ssephe 118295958Ssephe return hv_util_attach(dev); 119295958Ssephe} 120295958Ssephe 121295958Ssephestatic device_method_t heartbeat_methods[] = { 122295958Ssephe /* Device interface */ 123295958Ssephe DEVMETHOD(device_probe, hv_heartbeat_probe), 124295958Ssephe DEVMETHOD(device_attach, hv_heartbeat_attach), 125295958Ssephe DEVMETHOD(device_detach, hv_util_detach), 126295958Ssephe { 0, 0 } 127295958Ssephe}; 128295958Ssephe 129295958Ssephestatic driver_t heartbeat_driver = { "hvheartbeat", heartbeat_methods, sizeof(hv_util_sc)}; 130295958Ssephe 131295958Ssephestatic devclass_t heartbeat_devclass; 132295958Ssephe 133295958SsepheDRIVER_MODULE(hv_heartbeat, vmbus, heartbeat_driver, heartbeat_devclass, NULL, NULL); 134295958SsepheMODULE_VERSION(hv_heartbeat, 1); 135295958SsepheMODULE_DEPEND(hv_heartbeat, vmbus, 1, 1, 1); 136