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