1/*-
2 * Copyright (c) 2016 Microsoft Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#ifndef _VMBUS_REG_H_
30#define _VMBUS_REG_H_
31
32#include <sys/param.h>
33#include <dev/hyperv/include/hyperv.h> /* XXX for hyperv_guid */
34#include <dev/hyperv/include/vmbus.h>
35#include <dev/hyperv/vmbus/hyperv_reg.h>
36
37/*
38 * Hyper-V SynIC message format.
39 */
40
41#define VMBUS_MSG_DSIZE_MAX		240
42#define VMBUS_MSG_SIZE			256
43
44struct vmbus_message {
45	uint32_t	msg_type;	/* HYPERV_MSGTYPE_ */
46	uint8_t		msg_dsize;	/* data size */
47	uint8_t		msg_flags;	/* VMBUS_MSGFLAG_ */
48	uint16_t	msg_rsvd;
49	uint64_t	msg_id;
50	uint8_t		msg_data[VMBUS_MSG_DSIZE_MAX];
51} __packed;
52CTASSERT(sizeof(struct vmbus_message) == VMBUS_MSG_SIZE);
53
54#define VMBUS_MSGFLAG_PENDING		0x01
55
56/*
57 * Hyper-V SynIC event flags
58 */
59
60#ifdef __LP64__
61#define VMBUS_EVTFLAGS_MAX	32
62#define VMBUS_EVTFLAG_SHIFT	6
63#else
64#define VMBUS_EVTFLAGS_MAX	64
65#define VMBUS_EVTFLAG_SHIFT	5
66#endif
67#define VMBUS_EVTFLAG_LEN	(1 << VMBUS_EVTFLAG_SHIFT)
68#define VMBUS_EVTFLAG_MASK	(VMBUS_EVTFLAG_LEN - 1)
69#define VMBUS_EVTFLAGS_SIZE	256
70
71struct vmbus_evtflags {
72	u_long		evt_flags[VMBUS_EVTFLAGS_MAX];
73} __packed;
74CTASSERT(sizeof(struct vmbus_evtflags) == VMBUS_EVTFLAGS_SIZE);
75
76/*
77 * Hyper-V Monitor Notification Facility
78 */
79
80struct vmbus_mon_trig {
81	uint32_t	mt_pending;
82	uint32_t	mt_armed;
83} __packed;
84
85#define VMBUS_MONTRIGS_MAX	4
86#define VMBUS_MONTRIG_LEN	32
87
88struct vmbus_mnf {
89	uint32_t	mnf_state;
90	uint32_t	mnf_rsvd1;
91
92	struct vmbus_mon_trig mnf_trigs[VMBUS_MONTRIGS_MAX];
93	uint8_t		mnf_rsvd2[536];
94
95	uint16_t	mnf_lat[VMBUS_MONTRIGS_MAX][VMBUS_MONTRIG_LEN];
96	uint8_t		mnf_rsvd3[256];
97
98	struct hyperv_mon_param
99			mnf_param[VMBUS_MONTRIGS_MAX][VMBUS_MONTRIG_LEN];
100	uint8_t		mnf_rsvd4[1984];
101} __packed;
102CTASSERT(sizeof(struct vmbus_mnf) == PAGE_SIZE);
103
104/*
105 * Buffer ring
106 */
107struct vmbus_bufring {
108	/*
109	 * If br_windex == br_rindex, this bufring is empty; this
110	 * means we can _not_ write data to the bufring, if the
111	 * write is going to make br_windex same as br_rindex.
112	 */
113	volatile uint32_t	br_windex;
114	volatile uint32_t	br_rindex;
115
116	/*
117	 * Interrupt mask {0,1}
118	 *
119	 * For TX bufring, host set this to 1, when it is processing
120	 * the TX bufring, so that we can safely skip the TX event
121	 * notification to host.
122	 *
123	 * For RX bufring, once this is set to 1 by us, host will not
124	 * further dispatch interrupts to us, even if there are data
125	 * pending on the RX bufring.  This effectively disables the
126	 * interrupt of the channel to which this RX bufring is attached.
127	 */
128	volatile uint32_t	br_imask;
129
130	/*
131	 * WS2012/Win8 and later versions of Hyper-V implement interrupt
132	 * driven flow management. The feature bit feat_pending_snd_sz
133	 * is set by the host on the host->guest buffer ring, and by the
134	 * guest on the guest->host buffer ring.
135	 *
136	 * The meaning of the feature bit is a bit complex in that it has
137	 * semantics that apply to both buffer rings.  If the guest sets
138	 * the feature bit in the guest->host buffer ring, the guest is
139	 * telling the host that:
140	 * 1) It will set the br_pending_snd_sz field in the guest->host buffer
141	 *    ring when it is waiting for space to become available, and
142	 * 2) It will read the pending_send_sz field in the host->guest
143	 *    ring buffer and interrupt the host when it frees enough space
144	 *
145	 * Similarly, if the host sets the feature bit in the host->guest
146	 * ring buffer, the host is telling the guest that:
147	 * 1) It will set the pending_send_sz field in the host->guest ring
148	 *    buffer when it is waiting for space to become available, and
149	 * 2) It will read the pending_send_sz field in the guest->host
150	 *    ring buffer and interrupt the guest when it frees enough space
151	 *
152	 * If either the guest or host does not set the feature bit that it
153	 * owns, that guest or host must do polling if it encounters a full
154	 * ring buffer, and not signal the other end with an interrupt.
155	 */
156	volatile uint32_t	br_pending_snd_sz;
157	uint32_t		br_rsvd1[12];
158	union	{
159		struct {
160			uint32_t feat_pending_snd_sz:1;
161		};
162		uint32_t value;
163	} br_feature_bits;
164
165	/* Padding to PAGE_SIZE */
166	uint8_t			br_rsvd2[4020];
167
168	/*
169	 * Total guest to host interrupt count
170	 * - For rx ring, this counts the guest signaling host when this rx
171	 * ring changing from full to not full.
172	 *
173	 * - For tx ring, this counts the guest signaling host when this tx
174	 * ring changing from empty to non empty.
175	 */
176	uint64_t		br_g2h_intr_cnt;
177
178	uint8_t			br_data[];
179} __packed;
180CTASSERT(sizeof(struct vmbus_bufring) == PAGE_SIZE);
181
182/*
183 * Channel
184 */
185
186#define VMBUS_CHAN_MAX_COMPAT	256
187#define VMBUS_CHAN_MAX		(VMBUS_EVTFLAG_LEN * VMBUS_EVTFLAGS_MAX)
188
189/*
190 * Channel packets
191 */
192
193#define VMBUS_CHANPKT_SIZE_ALIGN	(1 << VMBUS_CHANPKT_SIZE_SHIFT)
194
195#define VMBUS_CHANPKT_SETLEN(pktlen, len)		\
196do {							\
197	(pktlen) = (len) >> VMBUS_CHANPKT_SIZE_SHIFT;	\
198} while (0)
199
200#define VMBUS_CHANPKT_TOTLEN(tlen)	\
201	roundup2((tlen), VMBUS_CHANPKT_SIZE_ALIGN)
202
203#define VMBUS_CHANPKT_HLEN_MIN		\
204	(sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT)
205
206struct vmbus_chanpkt {
207	struct vmbus_chanpkt_hdr cp_hdr;
208} __packed;
209
210struct vmbus_chanpkt_sglist {
211	struct vmbus_chanpkt_hdr cp_hdr;
212	uint32_t	cp_rsvd;
213	uint32_t	cp_gpa_cnt;
214	struct vmbus_gpa cp_gpa[];
215} __packed;
216
217struct vmbus_chanpkt_prplist {
218	struct vmbus_chanpkt_hdr cp_hdr;
219	uint32_t	cp_rsvd;
220	uint32_t	cp_range_cnt;
221	struct vmbus_gpa_range cp_range[];
222} __packed;
223
224/*
225 * Channel messages
226 * - Embedded in vmbus_message.msg_data, e.g. response and notification.
227 * - Embedded in hypercall_postmsg_in.hc_data, e.g. request.
228 */
229
230#define VMBUS_CHANMSG_TYPE_CHOFFER		1	/* NOTE */
231#define VMBUS_CHANMSG_TYPE_CHRESCIND		2	/* NOTE */
232#define VMBUS_CHANMSG_TYPE_CHREQUEST		3	/* REQ */
233#define VMBUS_CHANMSG_TYPE_CHOFFER_DONE		4	/* NOTE */
234#define VMBUS_CHANMSG_TYPE_CHOPEN		5	/* REQ */
235#define VMBUS_CHANMSG_TYPE_CHOPEN_RESP		6	/* RESP */
236#define VMBUS_CHANMSG_TYPE_CHCLOSE		7	/* REQ */
237#define VMBUS_CHANMSG_TYPE_GPADL_CONN		8	/* REQ */
238#define VMBUS_CHANMSG_TYPE_GPADL_SUBCONN	9	/* REQ */
239#define VMBUS_CHANMSG_TYPE_GPADL_CONNRESP	10	/* RESP */
240#define VMBUS_CHANMSG_TYPE_GPADL_DISCONN	11	/* REQ */
241#define VMBUS_CHANMSG_TYPE_GPADL_DISCONNRESP	12	/* RESP */
242#define VMBUS_CHANMSG_TYPE_CHFREE		13	/* REQ */
243#define VMBUS_CHANMSG_TYPE_CONNECT		14	/* REQ */
244#define VMBUS_CHANMSG_TYPE_CONNECT_RESP		15	/* RESP */
245#define VMBUS_CHANMSG_TYPE_DISCONNECT		16	/* REQ */
246#define VMBUS_CHANMSG_TYPE_17			17
247#define VMBUS_CHANMSG_TYPE_18			18
248#define VMBUS_CHANMSG_TYPE_19			19
249#define VMBUS_CHANMSG_TYPE_20			20
250#define VMBUS_CHANMSG_TYPE_TL_CONN		21	/* REQ */
251#define VMBUS_CHANMSG_TYPE_22			22
252#define VMBUS_CHANMSG_TYPE_TL_RESULT		23	/* RESP */
253#define VMBUS_CHANMSG_TYPE_MAX			24
254
255struct vmbus_chanmsg_hdr {
256	uint32_t	chm_type;	/* VMBUS_CHANMSG_TYPE_ */
257	uint32_t	chm_rsvd;
258} __packed;
259
260/* VMBUS_CHANMSG_TYPE_CONNECT */
261struct vmbus_chanmsg_connect {
262	struct vmbus_chanmsg_hdr chm_hdr;
263	uint32_t	chm_ver;
264	uint32_t	chm_rsvd;
265	uint64_t	chm_evtflags;
266	uint64_t	chm_mnf1;
267	uint64_t	chm_mnf2;
268} __packed;
269
270/* VMBUS_CHANMSG_TYPE_CONNECT_RESP */
271struct vmbus_chanmsg_connect_resp {
272	struct vmbus_chanmsg_hdr chm_hdr;
273	uint8_t		chm_done;
274} __packed;
275
276/* VMBUS_CHANMSG_TYPE_CHREQUEST */
277struct vmbus_chanmsg_chrequest {
278	struct vmbus_chanmsg_hdr chm_hdr;
279} __packed;
280
281/* VMBUS_CHANMSG_TYPE_DISCONNECT */
282struct vmbus_chanmsg_disconnect {
283	struct vmbus_chanmsg_hdr chm_hdr;
284} __packed;
285
286/* VMBUS_CHANMSG_TYPE_TL_CONN */
287/* Hyper-V socket guest connect request */
288struct vmbus_chanmsg_tl_connect {
289	struct vmbus_chanmsg_hdr chm_hdr;
290	struct hyperv_guid guest_endpoint_id;
291	struct hyperv_guid host_service_id;
292} __packed;
293
294
295/* VMBUS_CHANMSG_TYPE_CHOPEN */
296struct vmbus_chanmsg_chopen {
297	struct vmbus_chanmsg_hdr chm_hdr;
298	uint32_t	chm_chanid;
299	uint32_t	chm_openid;
300	uint32_t	chm_gpadl;
301	uint32_t	chm_vcpuid;
302	uint32_t	chm_txbr_pgcnt;
303#define VMBUS_CHANMSG_CHOPEN_UDATA_SIZE	120
304	uint8_t		chm_udata[VMBUS_CHANMSG_CHOPEN_UDATA_SIZE];
305} __packed;
306
307/* VMBUS_CHANMSG_TYPE_CHOPEN_RESP */
308struct vmbus_chanmsg_chopen_resp {
309	struct vmbus_chanmsg_hdr chm_hdr;
310	uint32_t	chm_chanid;
311	uint32_t	chm_openid;
312	uint32_t	chm_status;
313} __packed;
314
315/* VMBUS_CHANMSG_TYPE_GPADL_CONN */
316struct vmbus_chanmsg_gpadl_conn {
317	struct vmbus_chanmsg_hdr chm_hdr;
318	uint32_t	chm_chanid;
319	uint32_t	chm_gpadl;
320	uint16_t	chm_range_len;
321	uint16_t	chm_range_cnt;
322	struct vmbus_gpa_range chm_range;
323} __packed;
324
325#define VMBUS_CHANMSG_GPADL_CONN_PGMAX		26
326CTASSERT(__offsetof(struct vmbus_chanmsg_gpadl_conn,
327    chm_range.gpa_page[VMBUS_CHANMSG_GPADL_CONN_PGMAX]) <=
328    HYPERCALL_POSTMSGIN_DSIZE_MAX);
329
330/* VMBUS_CHANMSG_TYPE_GPADL_SUBCONN */
331struct vmbus_chanmsg_gpadl_subconn {
332	struct vmbus_chanmsg_hdr chm_hdr;
333	uint32_t	chm_msgno;
334	uint32_t	chm_gpadl;
335	uint64_t	chm_gpa_page[];
336} __packed;
337
338#define VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX	28
339CTASSERT(__offsetof(struct vmbus_chanmsg_gpadl_subconn,
340    chm_gpa_page[VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX]) <=
341    HYPERCALL_POSTMSGIN_DSIZE_MAX);
342
343/* VMBUS_CHANMSG_TYPE_GPADL_CONNRESP */
344struct vmbus_chanmsg_gpadl_connresp {
345	struct vmbus_chanmsg_hdr chm_hdr;
346	uint32_t	chm_chanid;
347	uint32_t	chm_gpadl;
348	uint32_t	chm_status;
349} __packed;
350
351/* VMBUS_CHANMSG_TYPE_CHCLOSE */
352struct vmbus_chanmsg_chclose {
353	struct vmbus_chanmsg_hdr chm_hdr;
354	uint32_t	chm_chanid;
355} __packed;
356
357/* VMBUS_CHANMSG_TYPE_GPADL_DISCONN */
358struct vmbus_chanmsg_gpadl_disconn {
359	struct vmbus_chanmsg_hdr chm_hdr;
360	uint32_t	chm_chanid;
361	uint32_t	chm_gpadl;
362} __packed;
363
364/* VMBUS_CHANMSG_TYPE_CHFREE */
365struct vmbus_chanmsg_chfree {
366	struct vmbus_chanmsg_hdr chm_hdr;
367	uint32_t	chm_chanid;
368} __packed;
369
370/* VMBUS_CHANMSG_TYPE_CHRESCIND */
371struct vmbus_chanmsg_chrescind {
372	struct vmbus_chanmsg_hdr chm_hdr;
373	uint32_t	chm_chanid;
374} __packed;
375
376/* Size of the user defined data buffer for non-pipe offers */
377#define VMBUS_CHANMSG_CHOFFER_UDATA_SIZE		120
378
379/* Size of the user defined data buffer for pipe offers. */
380#define VMBUS_CHANMSG_CHOFFER_UDATA_PIPE_SIZE		116
381
382/* VMBUS_CHANMSG_TYPE_CHOFFER */
383struct vmbus_chanmsg_choffer {
384	struct vmbus_chanmsg_hdr chm_hdr;
385	struct hyperv_guid chm_chtype;
386	struct hyperv_guid chm_chinst;
387	uint64_t	chm_chlat;	/* unit: 100ns */
388	uint32_t	chm_chrev;
389	uint32_t	chm_svrctx_sz;
390	uint16_t	chm_chflags;
391	uint16_t	chm_mmio_sz;	/* unit: MB */
392
393	union {
394		/* Non-pipes */
395		struct {
396			uint8_t	user_def[VMBUS_CHANMSG_CHOFFER_UDATA_SIZE];
397		} std;
398		/*
399		 * Pipes:
400		 * For integrated pipe protocol, which is implemented on
401		 * top of standard user-defined data. Pipe clients have
402		 * VMBUS_CHANMSG_CHOFFER_UDATA_PIPE_SIZE bytes left for
403		 * their own user.
404		 */
405		struct {
406			uint32_t pipe_mode;
407			uint8_t
408			    user_def[VMBUS_CHANMSG_CHOFFER_UDATA_PIPE_SIZE];
409		} pipe;
410	} chm_udata;
411
412	uint16_t	chm_subidx;
413	uint16_t	chm_rsvd;
414	uint32_t	chm_chanid;
415	uint8_t		chm_montrig;
416	uint8_t		chm_flags1;	/* VMBUS_CHOFFER_FLAG1_ */
417	uint16_t	chm_flags2;
418	uint32_t	chm_connid;
419} __packed;
420CTASSERT(sizeof(struct vmbus_chanmsg_choffer) <= VMBUS_MSG_DSIZE_MAX);
421
422/* Server Flag */
423#define VMBUS_CHAN_TLNPI_PROVIDER_OFFER			0x2000
424
425#define VMBUS_CHOFFER_FLAG1_HASMNF	0x01
426
427#endif	/* !_VMBUS_REG_H_ */
428