vmbus_ic.c revision 303824
1250199Sgrehan/*- 2298446Ssephe * Copyright (c) 2014,2016 Microsoft Corp. 3250199Sgrehan * All rights reserved. 4250199Sgrehan * 5250199Sgrehan * Redistribution and use in source and binary forms, with or without 6250199Sgrehan * modification, are permitted provided that the following conditions 7250199Sgrehan * are met: 8250199Sgrehan * 1. Redistributions of source code must retain the above copyright 9250199Sgrehan * notice unmodified, this list of conditions, and the following 10250199Sgrehan * disclaimer. 11250199Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 12250199Sgrehan * notice, this list of conditions and the following disclaimer in the 13250199Sgrehan * documentation and/or other materials provided with the distribution. 14250199Sgrehan * 15250199Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16250199Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17250199Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18250199Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19250199Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20250199Sgrehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21250199Sgrehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22250199Sgrehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23250199Sgrehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24250199Sgrehan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25271493Sdelphij * 26271493Sdelphij * $FreeBSD: head/sys/dev/hyperv/utilities/hv_util.c 303824 2016-08-08 06:18:54Z sephe $ 27250199Sgrehan */ 28250199Sgrehan 29271493Sdelphij/* 30250199Sgrehan * A common driver for all hyper-V util services. 31250199Sgrehan */ 32250199Sgrehan 33250199Sgrehan#include <sys/param.h> 34250199Sgrehan#include <sys/kernel.h> 35250199Sgrehan#include <sys/bus.h> 36250199Sgrehan#include <sys/malloc.h> 37250199Sgrehan#include <sys/module.h> 38250199Sgrehan#include <sys/reboot.h> 39250199Sgrehan#include <sys/timetc.h> 40255414Sgrehan#include <sys/syscallsubr.h> 41250199Sgrehan 42250199Sgrehan#include <dev/hyperv/include/hyperv.h> 43303021Ssephe#include <dev/hyperv/include/vmbus.h> 44303067Ssephe#include <dev/hyperv/utilities/hv_utilreg.h> 45295958Ssephe#include "hv_util.h" 46250199Sgrehan 47303823Ssephe#define VMBUS_IC_BRSIZE (4 * PAGE_SIZE) 48303823Ssephe 49295958Ssephevoid 50303822Ssephehv_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, uint8_t *buf) 51255414Sgrehan{ 52303822Ssephe struct hv_vmbus_icmsg_negotiate *negop; 53303822Ssephe 54250199Sgrehan icmsghdrp->icmsgsize = 0x10; 55250199Sgrehan 56250199Sgrehan negop = (struct hv_vmbus_icmsg_negotiate *)&buf[ 57250199Sgrehan sizeof(struct hv_vmbus_pipe_hdr) + 58250199Sgrehan sizeof(struct hv_vmbus_icmsg_hdr)]; 59250199Sgrehan 60255414Sgrehan if (negop->icframe_vercnt >= 2 && 61250199Sgrehan negop->icversion_data[1].major == 3) { 62250199Sgrehan negop->icversion_data[0].major = 3; 63250199Sgrehan negop->icversion_data[0].minor = 0; 64250199Sgrehan negop->icversion_data[1].major = 3; 65250199Sgrehan negop->icversion_data[1].minor = 0; 66250199Sgrehan } else { 67250199Sgrehan negop->icversion_data[0].major = 1; 68250199Sgrehan negop->icversion_data[0].minor = 0; 69250199Sgrehan negop->icversion_data[1].major = 1; 70250199Sgrehan negop->icversion_data[1].minor = 0; 71250199Sgrehan } 72250199Sgrehan 73250199Sgrehan negop->icframe_vercnt = 1; 74250199Sgrehan negop->icmsg_vercnt = 1; 75250199Sgrehan} 76250199Sgrehan 77295958Ssepheint 78303824Ssephehv_util_attach(device_t dev, vmbus_chan_callback_t cb) 79250199Sgrehan{ 80303823Ssephe struct hv_util_sc *sc = device_get_softc(dev); 81303823Ssephe struct vmbus_channel *chan = vmbus_get_channel(dev); 82303823Ssephe int error; 83250199Sgrehan 84303823Ssephe sc->ic_buflen = VMBUS_IC_BRSIZE; 85303823Ssephe sc->receive_buffer = malloc(VMBUS_IC_BRSIZE, M_DEVBUF, 86303823Ssephe M_WAITOK | M_ZERO); 87250199Sgrehan 88282212Swhu /* 89282212Swhu * These services are not performance critical and do not need 90282212Swhu * batched reading. Furthermore, some services such as KVP can 91282212Swhu * only handle one message from the host at a time. 92282212Swhu * Turn off batched reading for all util drivers before we open the 93282212Swhu * channel. 94282212Swhu */ 95303069Ssephe vmbus_chan_set_readbatch(chan, false); 96282212Swhu 97303823Ssephe error = vmbus_chan_open(chan, VMBUS_IC_BRSIZE, VMBUS_IC_BRSIZE, NULL, 0, 98303824Ssephe cb, sc); 99303823Ssephe if (error) { 100303823Ssephe free(sc->receive_buffer, M_DEVBUF); 101303823Ssephe return (error); 102303823Ssephe } 103250199Sgrehan return (0); 104250199Sgrehan} 105250199Sgrehan 106295958Ssepheint 107250199Sgrehanhv_util_detach(device_t dev) 108250199Sgrehan{ 109302702Ssephe struct hv_util_sc *sc = device_get_softc(dev); 110250199Sgrehan 111303069Ssephe vmbus_chan_close(vmbus_get_channel(dev)); 112302702Ssephe free(sc->receive_buffer, M_DEVBUF); 113250199Sgrehan 114250199Sgrehan return (0); 115250199Sgrehan} 116