xref: /linux-6.15/include/linux/hyperv.h (revision 63273cb4)
146a97191SGreg Kroah-Hartman /*
246a97191SGreg Kroah-Hartman  *
346a97191SGreg Kroah-Hartman  * Copyright (c) 2011, Microsoft Corporation.
446a97191SGreg Kroah-Hartman  *
546a97191SGreg Kroah-Hartman  * This program is free software; you can redistribute it and/or modify it
646a97191SGreg Kroah-Hartman  * under the terms and conditions of the GNU General Public License,
746a97191SGreg Kroah-Hartman  * version 2, as published by the Free Software Foundation.
846a97191SGreg Kroah-Hartman  *
946a97191SGreg Kroah-Hartman  * This program is distributed in the hope it will be useful, but WITHOUT
1046a97191SGreg Kroah-Hartman  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1146a97191SGreg Kroah-Hartman  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1246a97191SGreg Kroah-Hartman  * more details.
1346a97191SGreg Kroah-Hartman  *
1446a97191SGreg Kroah-Hartman  * You should have received a copy of the GNU General Public License along with
1546a97191SGreg Kroah-Hartman  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
1646a97191SGreg Kroah-Hartman  * Place - Suite 330, Boston, MA 02111-1307 USA.
1746a97191SGreg Kroah-Hartman  *
1846a97191SGreg Kroah-Hartman  * Authors:
1946a97191SGreg Kroah-Hartman  *   Haiyang Zhang <[email protected]>
2046a97191SGreg Kroah-Hartman  *   Hank Janssen  <[email protected]>
2146a97191SGreg Kroah-Hartman  *   K. Y. Srinivasan <[email protected]>
2246a97191SGreg Kroah-Hartman  *
2346a97191SGreg Kroah-Hartman  */
2446a97191SGreg Kroah-Hartman 
2546a97191SGreg Kroah-Hartman #ifndef _HYPERV_H
2646a97191SGreg Kroah-Hartman #define _HYPERV_H
2746a97191SGreg Kroah-Hartman 
285267cf02SBjarke Istrup Pedersen #include <uapi/linux/hyperv.h>
295267cf02SBjarke Istrup Pedersen 
302939437cSK. Y. Srinivasan #include <linux/types.h>
3146a97191SGreg Kroah-Hartman #include <linux/scatterlist.h>
3246a97191SGreg Kroah-Hartman #include <linux/list.h>
3346a97191SGreg Kroah-Hartman #include <linux/timer.h>
3446a97191SGreg Kroah-Hartman #include <linux/completion.h>
3546a97191SGreg Kroah-Hartman #include <linux/device.h>
3646a97191SGreg Kroah-Hartman #include <linux/mod_devicetable.h>
37631e63a9SStephen Hemminger #include <linux/interrupt.h>
38*63273cb4SLong Li #include <linux/reciprocal_div.h>
3946a97191SGreg Kroah-Hartman 
407e5ec368SK. Y. Srinivasan #define MAX_PAGE_BUFFER_COUNT				32
4146a97191SGreg Kroah-Hartman #define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
4246a97191SGreg Kroah-Hartman 
4346a97191SGreg Kroah-Hartman #pragma pack(push, 1)
4446a97191SGreg Kroah-Hartman 
4546a97191SGreg Kroah-Hartman /* Single-page buffer */
4646a97191SGreg Kroah-Hartman struct hv_page_buffer {
4746a97191SGreg Kroah-Hartman 	u32 len;
4846a97191SGreg Kroah-Hartman 	u32 offset;
4946a97191SGreg Kroah-Hartman 	u64 pfn;
5046a97191SGreg Kroah-Hartman };
5146a97191SGreg Kroah-Hartman 
5246a97191SGreg Kroah-Hartman /* Multiple-page buffer */
5346a97191SGreg Kroah-Hartman struct hv_multipage_buffer {
5446a97191SGreg Kroah-Hartman 	/* Length and Offset determines the # of pfns in the array */
5546a97191SGreg Kroah-Hartman 	u32 len;
5646a97191SGreg Kroah-Hartman 	u32 offset;
5746a97191SGreg Kroah-Hartman 	u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT];
5846a97191SGreg Kroah-Hartman };
5946a97191SGreg Kroah-Hartman 
60d61031eeSK. Y. Srinivasan /*
61d61031eeSK. Y. Srinivasan  * Multiple-page buffer array; the pfn array is variable size:
62d61031eeSK. Y. Srinivasan  * The number of entries in the PFN array is determined by
63d61031eeSK. Y. Srinivasan  * "len" and "offset".
64d61031eeSK. Y. Srinivasan  */
65d61031eeSK. Y. Srinivasan struct hv_mpb_array {
66d61031eeSK. Y. Srinivasan 	/* Length and Offset determines the # of pfns in the array */
67d61031eeSK. Y. Srinivasan 	u32 len;
68d61031eeSK. Y. Srinivasan 	u32 offset;
69d61031eeSK. Y. Srinivasan 	u64 pfn_array[];
70d61031eeSK. Y. Srinivasan };
71d61031eeSK. Y. Srinivasan 
7246a97191SGreg Kroah-Hartman /* 0x18 includes the proprietary packet header */
7346a97191SGreg Kroah-Hartman #define MAX_PAGE_BUFFER_PACKET		(0x18 +			\
7446a97191SGreg Kroah-Hartman 					(sizeof(struct hv_page_buffer) * \
7546a97191SGreg Kroah-Hartman 					 MAX_PAGE_BUFFER_COUNT))
7646a97191SGreg Kroah-Hartman #define MAX_MULTIPAGE_BUFFER_PACKET	(0x18 +			\
7746a97191SGreg Kroah-Hartman 					 sizeof(struct hv_multipage_buffer))
7846a97191SGreg Kroah-Hartman 
7946a97191SGreg Kroah-Hartman 
8046a97191SGreg Kroah-Hartman #pragma pack(pop)
8146a97191SGreg Kroah-Hartman 
8246a97191SGreg Kroah-Hartman struct hv_ring_buffer {
8346a97191SGreg Kroah-Hartman 	/* Offset in bytes from the start of ring data below */
8446a97191SGreg Kroah-Hartman 	u32 write_index;
8546a97191SGreg Kroah-Hartman 
8646a97191SGreg Kroah-Hartman 	/* Offset in bytes from the start of ring data below */
8746a97191SGreg Kroah-Hartman 	u32 read_index;
8846a97191SGreg Kroah-Hartman 
8946a97191SGreg Kroah-Hartman 	u32 interrupt_mask;
9046a97191SGreg Kroah-Hartman 
912416603eSK. Y. Srinivasan 	/*
922416603eSK. Y. Srinivasan 	 * Win8 uses some of the reserved bits to implement
932416603eSK. Y. Srinivasan 	 * interrupt driven flow management. On the send side
942416603eSK. Y. Srinivasan 	 * we can request that the receiver interrupt the sender
952416603eSK. Y. Srinivasan 	 * when the ring transitions from being full to being able
962416603eSK. Y. Srinivasan 	 * to handle a message of size "pending_send_sz".
972416603eSK. Y. Srinivasan 	 *
982416603eSK. Y. Srinivasan 	 * Add necessary state for this enhancement.
9946a97191SGreg Kroah-Hartman 	 */
1002416603eSK. Y. Srinivasan 	u32 pending_send_sz;
1012416603eSK. Y. Srinivasan 
1022416603eSK. Y. Srinivasan 	u32 reserved1[12];
1032416603eSK. Y. Srinivasan 
1042416603eSK. Y. Srinivasan 	union {
1052416603eSK. Y. Srinivasan 		struct {
1062416603eSK. Y. Srinivasan 			u32 feat_pending_send_sz:1;
1072416603eSK. Y. Srinivasan 		};
1082416603eSK. Y. Srinivasan 		u32 value;
1092416603eSK. Y. Srinivasan 	} feature_bits;
1102416603eSK. Y. Srinivasan 
1112416603eSK. Y. Srinivasan 	/* Pad it to PAGE_SIZE so that data starts on page boundary */
1122416603eSK. Y. Srinivasan 	u8	reserved2[4028];
11346a97191SGreg Kroah-Hartman 
11446a97191SGreg Kroah-Hartman 	/*
11546a97191SGreg Kroah-Hartman 	 * Ring data starts here + RingDataStartOffset
11646a97191SGreg Kroah-Hartman 	 * !!! DO NOT place any fields below this !!!
11746a97191SGreg Kroah-Hartman 	 */
11846a97191SGreg Kroah-Hartman 	u8 buffer[0];
11946a97191SGreg Kroah-Hartman } __packed;
12046a97191SGreg Kroah-Hartman 
12146a97191SGreg Kroah-Hartman struct hv_ring_buffer_info {
12246a97191SGreg Kroah-Hartman 	struct hv_ring_buffer *ring_buffer;
12346a97191SGreg Kroah-Hartman 	u32 ring_size;			/* Include the shared header */
124*63273cb4SLong Li 	struct reciprocal_value ring_size_div10_reciprocal;
12546a97191SGreg Kroah-Hartman 	spinlock_t ring_lock;
12646a97191SGreg Kroah-Hartman 
12746a97191SGreg Kroah-Hartman 	u32 ring_datasize;		/* < ring_size */
128ab028db4SK. Y. Srinivasan 	u32 priv_read_index;
12946a97191SGreg Kroah-Hartman };
13046a97191SGreg Kroah-Hartman 
13133be96e4SHaiyang Zhang 
132e4165a0fSStephen Hemminger static inline u32 hv_get_bytes_to_read(const struct hv_ring_buffer_info *rbi)
133a6341f00SK. Y. Srinivasan {
134a6341f00SK. Y. Srinivasan 	u32 read_loc, write_loc, dsize, read;
135a6341f00SK. Y. Srinivasan 
136a6341f00SK. Y. Srinivasan 	dsize = rbi->ring_datasize;
137a6341f00SK. Y. Srinivasan 	read_loc = rbi->ring_buffer->read_index;
138a6341f00SK. Y. Srinivasan 	write_loc = READ_ONCE(rbi->ring_buffer->write_index);
139a6341f00SK. Y. Srinivasan 
140a6341f00SK. Y. Srinivasan 	read = write_loc >= read_loc ? (write_loc - read_loc) :
141a6341f00SK. Y. Srinivasan 		(dsize - read_loc) + write_loc;
142a6341f00SK. Y. Srinivasan 
143a6341f00SK. Y. Srinivasan 	return read;
144a6341f00SK. Y. Srinivasan }
145a6341f00SK. Y. Srinivasan 
146e4165a0fSStephen Hemminger static inline u32 hv_get_bytes_to_write(const struct hv_ring_buffer_info *rbi)
147a6341f00SK. Y. Srinivasan {
148a6341f00SK. Y. Srinivasan 	u32 read_loc, write_loc, dsize, write;
149a6341f00SK. Y. Srinivasan 
150a6341f00SK. Y. Srinivasan 	dsize = rbi->ring_datasize;
151a6341f00SK. Y. Srinivasan 	read_loc = READ_ONCE(rbi->ring_buffer->read_index);
152a6341f00SK. Y. Srinivasan 	write_loc = rbi->ring_buffer->write_index;
153a6341f00SK. Y. Srinivasan 
154a6341f00SK. Y. Srinivasan 	write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
155a6341f00SK. Y. Srinivasan 		read_loc - write_loc;
156a6341f00SK. Y. Srinivasan 	return write;
157a6341f00SK. Y. Srinivasan }
158a6341f00SK. Y. Srinivasan 
159*63273cb4SLong Li static inline u32 hv_get_avail_to_write_percent(
160*63273cb4SLong Li 		const struct hv_ring_buffer_info *rbi)
161*63273cb4SLong Li {
162*63273cb4SLong Li 	u32 avail_write = hv_get_bytes_to_write(rbi);
163*63273cb4SLong Li 
164*63273cb4SLong Li 	return reciprocal_divide(
165*63273cb4SLong Li 			(avail_write  << 3) + (avail_write << 1),
166*63273cb4SLong Li 			rbi->ring_size_div10_reciprocal);
167*63273cb4SLong Li }
168*63273cb4SLong Li 
169eafa7072SK. Y. Srinivasan /*
170eafa7072SK. Y. Srinivasan  * VMBUS version is 32 bit entity broken up into
171eafa7072SK. Y. Srinivasan  * two 16 bit quantities: major_number. minor_number.
172eafa7072SK. Y. Srinivasan  *
173eafa7072SK. Y. Srinivasan  * 0 . 13 (Windows Server 2008)
174eafa7072SK. Y. Srinivasan  * 1 . 1  (Windows 7)
175eafa7072SK. Y. Srinivasan  * 2 . 4  (Windows 8)
17603367ef5SK. Y. Srinivasan  * 3 . 0  (Windows 8 R2)
1776c4e5f9cSKeith Mange  * 4 . 0  (Windows 10)
178eafa7072SK. Y. Srinivasan  */
179eafa7072SK. Y. Srinivasan 
180eafa7072SK. Y. Srinivasan #define VERSION_WS2008  ((0 << 16) | (13))
181eafa7072SK. Y. Srinivasan #define VERSION_WIN7    ((1 << 16) | (1))
182eafa7072SK. Y. Srinivasan #define VERSION_WIN8    ((2 << 16) | (4))
18303367ef5SK. Y. Srinivasan #define VERSION_WIN8_1    ((3 << 16) | (0))
1846c4e5f9cSKeith Mange #define VERSION_WIN10	((4 << 16) | (0))
185eafa7072SK. Y. Srinivasan 
186eafa7072SK. Y. Srinivasan #define VERSION_INVAL -1
187eafa7072SK. Y. Srinivasan 
1886c4e5f9cSKeith Mange #define VERSION_CURRENT VERSION_WIN10
18946a97191SGreg Kroah-Hartman 
19046a97191SGreg Kroah-Hartman /* Make maximum size of pipe payload of 16K */
19146a97191SGreg Kroah-Hartman #define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
19246a97191SGreg Kroah-Hartman 
19346a97191SGreg Kroah-Hartman /* Define PipeMode values. */
19446a97191SGreg Kroah-Hartman #define VMBUS_PIPE_TYPE_BYTE		0x00000000
19546a97191SGreg Kroah-Hartman #define VMBUS_PIPE_TYPE_MESSAGE		0x00000004
19646a97191SGreg Kroah-Hartman 
19746a97191SGreg Kroah-Hartman /* The size of the user defined data buffer for non-pipe offers. */
19846a97191SGreg Kroah-Hartman #define MAX_USER_DEFINED_BYTES		120
19946a97191SGreg Kroah-Hartman 
20046a97191SGreg Kroah-Hartman /* The size of the user defined data buffer for pipe offers. */
20146a97191SGreg Kroah-Hartman #define MAX_PIPE_USER_DEFINED_BYTES	116
20246a97191SGreg Kroah-Hartman 
20346a97191SGreg Kroah-Hartman /*
20446a97191SGreg Kroah-Hartman  * At the center of the Channel Management library is the Channel Offer. This
20546a97191SGreg Kroah-Hartman  * struct contains the fundamental information about an offer.
20646a97191SGreg Kroah-Hartman  */
20746a97191SGreg Kroah-Hartman struct vmbus_channel_offer {
20846a97191SGreg Kroah-Hartman 	uuid_le if_type;
20946a97191SGreg Kroah-Hartman 	uuid_le if_instance;
21029423b7eSK. Y. Srinivasan 
21129423b7eSK. Y. Srinivasan 	/*
21229423b7eSK. Y. Srinivasan 	 * These two fields are not currently used.
21329423b7eSK. Y. Srinivasan 	 */
21429423b7eSK. Y. Srinivasan 	u64 reserved1;
21529423b7eSK. Y. Srinivasan 	u64 reserved2;
21629423b7eSK. Y. Srinivasan 
21746a97191SGreg Kroah-Hartman 	u16 chn_flags;
21846a97191SGreg Kroah-Hartman 	u16 mmio_megabytes;		/* in bytes * 1024 * 1024 */
21946a97191SGreg Kroah-Hartman 
22046a97191SGreg Kroah-Hartman 	union {
22146a97191SGreg Kroah-Hartman 		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
22246a97191SGreg Kroah-Hartman 		struct {
22346a97191SGreg Kroah-Hartman 			unsigned char user_def[MAX_USER_DEFINED_BYTES];
22446a97191SGreg Kroah-Hartman 		} std;
22546a97191SGreg Kroah-Hartman 
22646a97191SGreg Kroah-Hartman 		/*
22746a97191SGreg Kroah-Hartman 		 * Pipes:
22846a97191SGreg Kroah-Hartman 		 * The following sructure is an integrated pipe protocol, which
22946a97191SGreg Kroah-Hartman 		 * is implemented on top of standard user-defined data. Pipe
23046a97191SGreg Kroah-Hartman 		 * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own
23146a97191SGreg Kroah-Hartman 		 * use.
23246a97191SGreg Kroah-Hartman 		 */
23346a97191SGreg Kroah-Hartman 		struct {
23446a97191SGreg Kroah-Hartman 			u32  pipe_mode;
23546a97191SGreg Kroah-Hartman 			unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES];
23646a97191SGreg Kroah-Hartman 		} pipe;
23746a97191SGreg Kroah-Hartman 	} u;
23829423b7eSK. Y. Srinivasan 	/*
23929423b7eSK. Y. Srinivasan 	 * The sub_channel_index is defined in win8.
24029423b7eSK. Y. Srinivasan 	 */
24129423b7eSK. Y. Srinivasan 	u16 sub_channel_index;
24229423b7eSK. Y. Srinivasan 	u16 reserved3;
24346a97191SGreg Kroah-Hartman } __packed;
24446a97191SGreg Kroah-Hartman 
24546a97191SGreg Kroah-Hartman /* Server Flags */
24646a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
24746a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES	2
24846a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS		4
24946a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_NAMED_PIPE_MODE			0x10
25046a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_LOOPBACK_OFFER			0x100
25146a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_PARENT_OFFER			0x200
25246a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION	0x400
253e8d6ca02SDexuan Cui #define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER		0x2000
25446a97191SGreg Kroah-Hartman 
25546a97191SGreg Kroah-Hartman struct vmpacket_descriptor {
25646a97191SGreg Kroah-Hartman 	u16 type;
25746a97191SGreg Kroah-Hartman 	u16 offset8;
25846a97191SGreg Kroah-Hartman 	u16 len8;
25946a97191SGreg Kroah-Hartman 	u16 flags;
26046a97191SGreg Kroah-Hartman 	u64 trans_id;
26146a97191SGreg Kroah-Hartman } __packed;
26246a97191SGreg Kroah-Hartman 
26346a97191SGreg Kroah-Hartman struct vmpacket_header {
26446a97191SGreg Kroah-Hartman 	u32 prev_pkt_start_offset;
26546a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor descriptor;
26646a97191SGreg Kroah-Hartman } __packed;
26746a97191SGreg Kroah-Hartman 
26846a97191SGreg Kroah-Hartman struct vmtransfer_page_range {
26946a97191SGreg Kroah-Hartman 	u32 byte_count;
27046a97191SGreg Kroah-Hartman 	u32 byte_offset;
27146a97191SGreg Kroah-Hartman } __packed;
27246a97191SGreg Kroah-Hartman 
27346a97191SGreg Kroah-Hartman struct vmtransfer_page_packet_header {
27446a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
27546a97191SGreg Kroah-Hartman 	u16 xfer_pageset_id;
2761508d811SK. Y. Srinivasan 	u8  sender_owns_set;
27746a97191SGreg Kroah-Hartman 	u8 reserved;
27846a97191SGreg Kroah-Hartman 	u32 range_cnt;
27946a97191SGreg Kroah-Hartman 	struct vmtransfer_page_range ranges[1];
28046a97191SGreg Kroah-Hartman } __packed;
28146a97191SGreg Kroah-Hartman 
28246a97191SGreg Kroah-Hartman struct vmgpadl_packet_header {
28346a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
28446a97191SGreg Kroah-Hartman 	u32 gpadl;
28546a97191SGreg Kroah-Hartman 	u32 reserved;
28646a97191SGreg Kroah-Hartman } __packed;
28746a97191SGreg Kroah-Hartman 
28846a97191SGreg Kroah-Hartman struct vmadd_remove_transfer_page_set {
28946a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
29046a97191SGreg Kroah-Hartman 	u32 gpadl;
29146a97191SGreg Kroah-Hartman 	u16 xfer_pageset_id;
29246a97191SGreg Kroah-Hartman 	u16 reserved;
29346a97191SGreg Kroah-Hartman } __packed;
29446a97191SGreg Kroah-Hartman 
29546a97191SGreg Kroah-Hartman /*
29646a97191SGreg Kroah-Hartman  * This structure defines a range in guest physical space that can be made to
29746a97191SGreg Kroah-Hartman  * look virtually contiguous.
29846a97191SGreg Kroah-Hartman  */
29946a97191SGreg Kroah-Hartman struct gpa_range {
30046a97191SGreg Kroah-Hartman 	u32 byte_count;
30146a97191SGreg Kroah-Hartman 	u32 byte_offset;
30246a97191SGreg Kroah-Hartman 	u64 pfn_array[0];
30346a97191SGreg Kroah-Hartman };
30446a97191SGreg Kroah-Hartman 
30546a97191SGreg Kroah-Hartman /*
30646a97191SGreg Kroah-Hartman  * This is the format for an Establish Gpadl packet, which contains a handle by
30746a97191SGreg Kroah-Hartman  * which this GPADL will be known and a set of GPA ranges associated with it.
30846a97191SGreg Kroah-Hartman  * This can be converted to a MDL by the guest OS.  If there are multiple GPA
30946a97191SGreg Kroah-Hartman  * ranges, then the resulting MDL will be "chained," representing multiple VA
31046a97191SGreg Kroah-Hartman  * ranges.
31146a97191SGreg Kroah-Hartman  */
31246a97191SGreg Kroah-Hartman struct vmestablish_gpadl {
31346a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
31446a97191SGreg Kroah-Hartman 	u32 gpadl;
31546a97191SGreg Kroah-Hartman 	u32 range_cnt;
31646a97191SGreg Kroah-Hartman 	struct gpa_range range[1];
31746a97191SGreg Kroah-Hartman } __packed;
31846a97191SGreg Kroah-Hartman 
31946a97191SGreg Kroah-Hartman /*
32046a97191SGreg Kroah-Hartman  * This is the format for a Teardown Gpadl packet, which indicates that the
32146a97191SGreg Kroah-Hartman  * GPADL handle in the Establish Gpadl packet will never be referenced again.
32246a97191SGreg Kroah-Hartman  */
32346a97191SGreg Kroah-Hartman struct vmteardown_gpadl {
32446a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
32546a97191SGreg Kroah-Hartman 	u32 gpadl;
32646a97191SGreg Kroah-Hartman 	u32 reserved;	/* for alignment to a 8-byte boundary */
32746a97191SGreg Kroah-Hartman } __packed;
32846a97191SGreg Kroah-Hartman 
32946a97191SGreg Kroah-Hartman /*
33046a97191SGreg Kroah-Hartman  * This is the format for a GPA-Direct packet, which contains a set of GPA
33146a97191SGreg Kroah-Hartman  * ranges, in addition to commands and/or data.
33246a97191SGreg Kroah-Hartman  */
33346a97191SGreg Kroah-Hartman struct vmdata_gpa_direct {
33446a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
33546a97191SGreg Kroah-Hartman 	u32 reserved;
33646a97191SGreg Kroah-Hartman 	u32 range_cnt;
33746a97191SGreg Kroah-Hartman 	struct gpa_range range[1];
33846a97191SGreg Kroah-Hartman } __packed;
33946a97191SGreg Kroah-Hartman 
34046a97191SGreg Kroah-Hartman /* This is the format for a Additional Data Packet. */
34146a97191SGreg Kroah-Hartman struct vmadditional_data {
34246a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
34346a97191SGreg Kroah-Hartman 	u64 total_bytes;
34446a97191SGreg Kroah-Hartman 	u32 offset;
34546a97191SGreg Kroah-Hartman 	u32 byte_cnt;
34646a97191SGreg Kroah-Hartman 	unsigned char data[1];
34746a97191SGreg Kroah-Hartman } __packed;
34846a97191SGreg Kroah-Hartman 
34946a97191SGreg Kroah-Hartman union vmpacket_largest_possible_header {
35046a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor simple_hdr;
35146a97191SGreg Kroah-Hartman 	struct vmtransfer_page_packet_header xfer_page_hdr;
35246a97191SGreg Kroah-Hartman 	struct vmgpadl_packet_header gpadl_hdr;
35346a97191SGreg Kroah-Hartman 	struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr;
35446a97191SGreg Kroah-Hartman 	struct vmestablish_gpadl establish_gpadl_hdr;
35546a97191SGreg Kroah-Hartman 	struct vmteardown_gpadl teardown_gpadl_hdr;
35646a97191SGreg Kroah-Hartman 	struct vmdata_gpa_direct data_gpa_direct_hdr;
35746a97191SGreg Kroah-Hartman };
35846a97191SGreg Kroah-Hartman 
35946a97191SGreg Kroah-Hartman #define VMPACKET_DATA_START_ADDRESS(__packet)	\
36046a97191SGreg Kroah-Hartman 	(void *)(((unsigned char *)__packet) +	\
36146a97191SGreg Kroah-Hartman 	 ((struct vmpacket_descriptor)__packet)->offset8 * 8)
36246a97191SGreg Kroah-Hartman 
36346a97191SGreg Kroah-Hartman #define VMPACKET_DATA_LENGTH(__packet)		\
36446a97191SGreg Kroah-Hartman 	((((struct vmpacket_descriptor)__packet)->len8 -	\
36546a97191SGreg Kroah-Hartman 	  ((struct vmpacket_descriptor)__packet)->offset8) * 8)
36646a97191SGreg Kroah-Hartman 
36746a97191SGreg Kroah-Hartman #define VMPACKET_TRANSFER_MODE(__packet)	\
36846a97191SGreg Kroah-Hartman 	(((struct IMPACT)__packet)->type)
36946a97191SGreg Kroah-Hartman 
37046a97191SGreg Kroah-Hartman enum vmbus_packet_type {
37146a97191SGreg Kroah-Hartman 	VM_PKT_INVALID				= 0x0,
37246a97191SGreg Kroah-Hartman 	VM_PKT_SYNCH				= 0x1,
37346a97191SGreg Kroah-Hartman 	VM_PKT_ADD_XFER_PAGESET			= 0x2,
37446a97191SGreg Kroah-Hartman 	VM_PKT_RM_XFER_PAGESET			= 0x3,
37546a97191SGreg Kroah-Hartman 	VM_PKT_ESTABLISH_GPADL			= 0x4,
37646a97191SGreg Kroah-Hartman 	VM_PKT_TEARDOWN_GPADL			= 0x5,
37746a97191SGreg Kroah-Hartman 	VM_PKT_DATA_INBAND			= 0x6,
37846a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_XFER_PAGES		= 0x7,
37946a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_GPADL			= 0x8,
38046a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_GPA_DIRECT		= 0x9,
38146a97191SGreg Kroah-Hartman 	VM_PKT_CANCEL_REQUEST			= 0xa,
38246a97191SGreg Kroah-Hartman 	VM_PKT_COMP				= 0xb,
38346a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_ADDITIONAL_PKT	= 0xc,
38446a97191SGreg Kroah-Hartman 	VM_PKT_ADDITIONAL_DATA			= 0xd
38546a97191SGreg Kroah-Hartman };
38646a97191SGreg Kroah-Hartman 
38746a97191SGreg Kroah-Hartman #define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
38846a97191SGreg Kroah-Hartman 
38946a97191SGreg Kroah-Hartman 
39046a97191SGreg Kroah-Hartman /* Version 1 messages */
39146a97191SGreg Kroah-Hartman enum vmbus_channel_message_type {
39246a97191SGreg Kroah-Hartman 	CHANNELMSG_INVALID			=  0,
39346a97191SGreg Kroah-Hartman 	CHANNELMSG_OFFERCHANNEL		=  1,
39446a97191SGreg Kroah-Hartman 	CHANNELMSG_RESCIND_CHANNELOFFER	=  2,
39546a97191SGreg Kroah-Hartman 	CHANNELMSG_REQUESTOFFERS		=  3,
39646a97191SGreg Kroah-Hartman 	CHANNELMSG_ALLOFFERS_DELIVERED	=  4,
39746a97191SGreg Kroah-Hartman 	CHANNELMSG_OPENCHANNEL		=  5,
39846a97191SGreg Kroah-Hartman 	CHANNELMSG_OPENCHANNEL_RESULT		=  6,
39946a97191SGreg Kroah-Hartman 	CHANNELMSG_CLOSECHANNEL		=  7,
40046a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_HEADER		=  8,
40146a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_BODY			=  9,
40246a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_CREATED		= 10,
40346a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_TEARDOWN		= 11,
40446a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_TORNDOWN		= 12,
40546a97191SGreg Kroah-Hartman 	CHANNELMSG_RELID_RELEASED		= 13,
40646a97191SGreg Kroah-Hartman 	CHANNELMSG_INITIATE_CONTACT		= 14,
40746a97191SGreg Kroah-Hartman 	CHANNELMSG_VERSION_RESPONSE		= 15,
40846a97191SGreg Kroah-Hartman 	CHANNELMSG_UNLOAD			= 16,
4092db84effSK. Y. Srinivasan 	CHANNELMSG_UNLOAD_RESPONSE		= 17,
4105c23a1a5SDexuan Cui 	CHANNELMSG_18				= 18,
4115c23a1a5SDexuan Cui 	CHANNELMSG_19				= 19,
4125c23a1a5SDexuan Cui 	CHANNELMSG_20				= 20,
4135c23a1a5SDexuan Cui 	CHANNELMSG_TL_CONNECT_REQUEST		= 21,
41446a97191SGreg Kroah-Hartman 	CHANNELMSG_COUNT
41546a97191SGreg Kroah-Hartman };
41646a97191SGreg Kroah-Hartman 
41746a97191SGreg Kroah-Hartman struct vmbus_channel_message_header {
41846a97191SGreg Kroah-Hartman 	enum vmbus_channel_message_type msgtype;
41946a97191SGreg Kroah-Hartman 	u32 padding;
42046a97191SGreg Kroah-Hartman } __packed;
42146a97191SGreg Kroah-Hartman 
42246a97191SGreg Kroah-Hartman /* Query VMBus Version parameters */
42346a97191SGreg Kroah-Hartman struct vmbus_channel_query_vmbus_version {
42446a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
42546a97191SGreg Kroah-Hartman 	u32 version;
42646a97191SGreg Kroah-Hartman } __packed;
42746a97191SGreg Kroah-Hartman 
42846a97191SGreg Kroah-Hartman /* VMBus Version Supported parameters */
42946a97191SGreg Kroah-Hartman struct vmbus_channel_version_supported {
43046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
4311508d811SK. Y. Srinivasan 	u8 version_supported;
43246a97191SGreg Kroah-Hartman } __packed;
43346a97191SGreg Kroah-Hartman 
43446a97191SGreg Kroah-Hartman /* Offer Channel parameters */
43546a97191SGreg Kroah-Hartman struct vmbus_channel_offer_channel {
43646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
43746a97191SGreg Kroah-Hartman 	struct vmbus_channel_offer offer;
43846a97191SGreg Kroah-Hartman 	u32 child_relid;
43946a97191SGreg Kroah-Hartman 	u8 monitorid;
44029423b7eSK. Y. Srinivasan 	/*
44129423b7eSK. Y. Srinivasan 	 * win7 and beyond splits this field into a bit field.
44229423b7eSK. Y. Srinivasan 	 */
44329423b7eSK. Y. Srinivasan 	u8 monitor_allocated:1;
44429423b7eSK. Y. Srinivasan 	u8 reserved:7;
44529423b7eSK. Y. Srinivasan 	/*
44629423b7eSK. Y. Srinivasan 	 * These are new fields added in win7 and later.
44729423b7eSK. Y. Srinivasan 	 * Do not access these fields without checking the
44829423b7eSK. Y. Srinivasan 	 * negotiated protocol.
44929423b7eSK. Y. Srinivasan 	 *
45029423b7eSK. Y. Srinivasan 	 * If "is_dedicated_interrupt" is set, we must not set the
45129423b7eSK. Y. Srinivasan 	 * associated bit in the channel bitmap while sending the
45229423b7eSK. Y. Srinivasan 	 * interrupt to the host.
45329423b7eSK. Y. Srinivasan 	 *
45429423b7eSK. Y. Srinivasan 	 * connection_id is to be used in signaling the host.
45529423b7eSK. Y. Srinivasan 	 */
45629423b7eSK. Y. Srinivasan 	u16 is_dedicated_interrupt:1;
45729423b7eSK. Y. Srinivasan 	u16 reserved1:15;
45829423b7eSK. Y. Srinivasan 	u32 connection_id;
45946a97191SGreg Kroah-Hartman } __packed;
46046a97191SGreg Kroah-Hartman 
46146a97191SGreg Kroah-Hartman /* Rescind Offer parameters */
46246a97191SGreg Kroah-Hartman struct vmbus_channel_rescind_offer {
46346a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
46446a97191SGreg Kroah-Hartman 	u32 child_relid;
46546a97191SGreg Kroah-Hartman } __packed;
46646a97191SGreg Kroah-Hartman 
4674827ee1dSStephen Hemminger static inline u32
4684827ee1dSStephen Hemminger hv_ringbuffer_pending_size(const struct hv_ring_buffer_info *rbi)
4694827ee1dSStephen Hemminger {
4704827ee1dSStephen Hemminger 	return rbi->ring_buffer->pending_send_sz;
4714827ee1dSStephen Hemminger }
4724827ee1dSStephen Hemminger 
47346a97191SGreg Kroah-Hartman /*
47446a97191SGreg Kroah-Hartman  * Request Offer -- no parameters, SynIC message contains the partition ID
47546a97191SGreg Kroah-Hartman  * Set Snoop -- no parameters, SynIC message contains the partition ID
47646a97191SGreg Kroah-Hartman  * Clear Snoop -- no parameters, SynIC message contains the partition ID
47746a97191SGreg Kroah-Hartman  * All Offers Delivered -- no parameters, SynIC message contains the partition
47846a97191SGreg Kroah-Hartman  *		           ID
47946a97191SGreg Kroah-Hartman  * Flush Client -- no parameters, SynIC message contains the partition ID
48046a97191SGreg Kroah-Hartman  */
48146a97191SGreg Kroah-Hartman 
48246a97191SGreg Kroah-Hartman /* Open Channel parameters */
48346a97191SGreg Kroah-Hartman struct vmbus_channel_open_channel {
48446a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
48546a97191SGreg Kroah-Hartman 
48646a97191SGreg Kroah-Hartman 	/* Identifies the specific VMBus channel that is being opened. */
48746a97191SGreg Kroah-Hartman 	u32 child_relid;
48846a97191SGreg Kroah-Hartman 
48946a97191SGreg Kroah-Hartman 	/* ID making a particular open request at a channel offer unique. */
49046a97191SGreg Kroah-Hartman 	u32 openid;
49146a97191SGreg Kroah-Hartman 
49246a97191SGreg Kroah-Hartman 	/* GPADL for the channel's ring buffer. */
49346a97191SGreg Kroah-Hartman 	u32 ringbuffer_gpadlhandle;
49446a97191SGreg Kroah-Hartman 
495abbf3b2aSK. Y. Srinivasan 	/*
496abbf3b2aSK. Y. Srinivasan 	 * Starting with win8, this field will be used to specify
497abbf3b2aSK. Y. Srinivasan 	 * the target virtual processor on which to deliver the interrupt for
498abbf3b2aSK. Y. Srinivasan 	 * the host to guest communication.
499abbf3b2aSK. Y. Srinivasan 	 * Prior to win8, incoming channel interrupts would only
500abbf3b2aSK. Y. Srinivasan 	 * be delivered on cpu 0. Setting this value to 0 would
501abbf3b2aSK. Y. Srinivasan 	 * preserve the earlier behavior.
502abbf3b2aSK. Y. Srinivasan 	 */
503abbf3b2aSK. Y. Srinivasan 	u32 target_vp;
50446a97191SGreg Kroah-Hartman 
50546a97191SGreg Kroah-Hartman 	/*
50646a97191SGreg Kroah-Hartman 	 * The upstream ring buffer begins at offset zero in the memory
50746a97191SGreg Kroah-Hartman 	 * described by RingBufferGpadlHandle. The downstream ring buffer
50846a97191SGreg Kroah-Hartman 	 * follows it at this offset (in pages).
50946a97191SGreg Kroah-Hartman 	 */
51046a97191SGreg Kroah-Hartman 	u32 downstream_ringbuffer_pageoffset;
51146a97191SGreg Kroah-Hartman 
51246a97191SGreg Kroah-Hartman 	/* User-specific data to be passed along to the server endpoint. */
51346a97191SGreg Kroah-Hartman 	unsigned char userdata[MAX_USER_DEFINED_BYTES];
51446a97191SGreg Kroah-Hartman } __packed;
51546a97191SGreg Kroah-Hartman 
51646a97191SGreg Kroah-Hartman /* Open Channel Result parameters */
51746a97191SGreg Kroah-Hartman struct vmbus_channel_open_result {
51846a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
51946a97191SGreg Kroah-Hartman 	u32 child_relid;
52046a97191SGreg Kroah-Hartman 	u32 openid;
52146a97191SGreg Kroah-Hartman 	u32 status;
52246a97191SGreg Kroah-Hartman } __packed;
52346a97191SGreg Kroah-Hartman 
52446a97191SGreg Kroah-Hartman /* Close channel parameters; */
52546a97191SGreg Kroah-Hartman struct vmbus_channel_close_channel {
52646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
52746a97191SGreg Kroah-Hartman 	u32 child_relid;
52846a97191SGreg Kroah-Hartman } __packed;
52946a97191SGreg Kroah-Hartman 
53046a97191SGreg Kroah-Hartman /* Channel Message GPADL */
53146a97191SGreg Kroah-Hartman #define GPADL_TYPE_RING_BUFFER		1
53246a97191SGreg Kroah-Hartman #define GPADL_TYPE_SERVER_SAVE_AREA	2
53346a97191SGreg Kroah-Hartman #define GPADL_TYPE_TRANSACTION		8
53446a97191SGreg Kroah-Hartman 
53546a97191SGreg Kroah-Hartman /*
53646a97191SGreg Kroah-Hartman  * The number of PFNs in a GPADL message is defined by the number of
53746a97191SGreg Kroah-Hartman  * pages that would be spanned by ByteCount and ByteOffset.  If the
53846a97191SGreg Kroah-Hartman  * implied number of PFNs won't fit in this packet, there will be a
53946a97191SGreg Kroah-Hartman  * follow-up packet that contains more.
54046a97191SGreg Kroah-Hartman  */
54146a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_header {
54246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
54346a97191SGreg Kroah-Hartman 	u32 child_relid;
54446a97191SGreg Kroah-Hartman 	u32 gpadl;
54546a97191SGreg Kroah-Hartman 	u16 range_buflen;
54646a97191SGreg Kroah-Hartman 	u16 rangecount;
54746a97191SGreg Kroah-Hartman 	struct gpa_range range[0];
54846a97191SGreg Kroah-Hartman } __packed;
54946a97191SGreg Kroah-Hartman 
55046a97191SGreg Kroah-Hartman /* This is the followup packet that contains more PFNs. */
55146a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_body {
55246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
55346a97191SGreg Kroah-Hartman 	u32 msgnumber;
55446a97191SGreg Kroah-Hartman 	u32 gpadl;
55546a97191SGreg Kroah-Hartman 	u64 pfn[0];
55646a97191SGreg Kroah-Hartman } __packed;
55746a97191SGreg Kroah-Hartman 
55846a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_created {
55946a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
56046a97191SGreg Kroah-Hartman 	u32 child_relid;
56146a97191SGreg Kroah-Hartman 	u32 gpadl;
56246a97191SGreg Kroah-Hartman 	u32 creation_status;
56346a97191SGreg Kroah-Hartman } __packed;
56446a97191SGreg Kroah-Hartman 
56546a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_teardown {
56646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
56746a97191SGreg Kroah-Hartman 	u32 child_relid;
56846a97191SGreg Kroah-Hartman 	u32 gpadl;
56946a97191SGreg Kroah-Hartman } __packed;
57046a97191SGreg Kroah-Hartman 
57146a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_torndown {
57246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
57346a97191SGreg Kroah-Hartman 	u32 gpadl;
57446a97191SGreg Kroah-Hartman } __packed;
57546a97191SGreg Kroah-Hartman 
57646a97191SGreg Kroah-Hartman struct vmbus_channel_relid_released {
57746a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
57846a97191SGreg Kroah-Hartman 	u32 child_relid;
57946a97191SGreg Kroah-Hartman } __packed;
58046a97191SGreg Kroah-Hartman 
58146a97191SGreg Kroah-Hartman struct vmbus_channel_initiate_contact {
58246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
58346a97191SGreg Kroah-Hartman 	u32 vmbus_version_requested;
584e28bab48SK. Y. Srinivasan 	u32 target_vcpu; /* The VCPU the host should respond to */
58546a97191SGreg Kroah-Hartman 	u64 interrupt_page;
58646a97191SGreg Kroah-Hartman 	u64 monitor_page1;
58746a97191SGreg Kroah-Hartman 	u64 monitor_page2;
58846a97191SGreg Kroah-Hartman } __packed;
58946a97191SGreg Kroah-Hartman 
5905c23a1a5SDexuan Cui /* Hyper-V socket: guest's connect()-ing to host */
5915c23a1a5SDexuan Cui struct vmbus_channel_tl_connect_request {
5925c23a1a5SDexuan Cui 	struct vmbus_channel_message_header header;
5935c23a1a5SDexuan Cui 	uuid_le guest_endpoint_id;
5945c23a1a5SDexuan Cui 	uuid_le host_service_id;
5955c23a1a5SDexuan Cui } __packed;
5965c23a1a5SDexuan Cui 
59746a97191SGreg Kroah-Hartman struct vmbus_channel_version_response {
59846a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
5991508d811SK. Y. Srinivasan 	u8 version_supported;
60046a97191SGreg Kroah-Hartman } __packed;
60146a97191SGreg Kroah-Hartman 
60246a97191SGreg Kroah-Hartman enum vmbus_channel_state {
60346a97191SGreg Kroah-Hartman 	CHANNEL_OFFER_STATE,
60446a97191SGreg Kroah-Hartman 	CHANNEL_OPENING_STATE,
60546a97191SGreg Kroah-Hartman 	CHANNEL_OPEN_STATE,
606e68d2971SK. Y. Srinivasan 	CHANNEL_OPENED_STATE,
60746a97191SGreg Kroah-Hartman };
60846a97191SGreg Kroah-Hartman 
60946a97191SGreg Kroah-Hartman /*
61046a97191SGreg Kroah-Hartman  * Represents each channel msg on the vmbus connection This is a
61146a97191SGreg Kroah-Hartman  * variable-size data structure depending on the msg type itself
61246a97191SGreg Kroah-Hartman  */
61346a97191SGreg Kroah-Hartman struct vmbus_channel_msginfo {
61446a97191SGreg Kroah-Hartman 	/* Bookkeeping stuff */
61546a97191SGreg Kroah-Hartman 	struct list_head msglistentry;
61646a97191SGreg Kroah-Hartman 
61746a97191SGreg Kroah-Hartman 	/* So far, this is only used to handle gpadl body message */
61846a97191SGreg Kroah-Hartman 	struct list_head submsglist;
61946a97191SGreg Kroah-Hartman 
62046a97191SGreg Kroah-Hartman 	/* Synchronize the request/response if needed */
62146a97191SGreg Kroah-Hartman 	struct completion  waitevent;
622ccb61f8aSK. Y. Srinivasan 	struct vmbus_channel *waiting_channel;
62346a97191SGreg Kroah-Hartman 	union {
62446a97191SGreg Kroah-Hartman 		struct vmbus_channel_version_supported version_supported;
62546a97191SGreg Kroah-Hartman 		struct vmbus_channel_open_result open_result;
62646a97191SGreg Kroah-Hartman 		struct vmbus_channel_gpadl_torndown gpadl_torndown;
62746a97191SGreg Kroah-Hartman 		struct vmbus_channel_gpadl_created gpadl_created;
62846a97191SGreg Kroah-Hartman 		struct vmbus_channel_version_response version_response;
62946a97191SGreg Kroah-Hartman 	} response;
63046a97191SGreg Kroah-Hartman 
63146a97191SGreg Kroah-Hartman 	u32 msgsize;
63246a97191SGreg Kroah-Hartman 	/*
63346a97191SGreg Kroah-Hartman 	 * The channel message that goes out on the "wire".
63446a97191SGreg Kroah-Hartman 	 * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header
63546a97191SGreg Kroah-Hartman 	 */
63646a97191SGreg Kroah-Hartman 	unsigned char msg[0];
63746a97191SGreg Kroah-Hartman };
63846a97191SGreg Kroah-Hartman 
63946a97191SGreg Kroah-Hartman struct vmbus_close_msg {
64046a97191SGreg Kroah-Hartman 	struct vmbus_channel_msginfo info;
64146a97191SGreg Kroah-Hartman 	struct vmbus_channel_close_channel msg;
64246a97191SGreg Kroah-Hartman };
64346a97191SGreg Kroah-Hartman 
644b3bf60c7SK. Y. Srinivasan /* Define connection identifier type. */
645b3bf60c7SK. Y. Srinivasan union hv_connection_id {
646b3bf60c7SK. Y. Srinivasan 	u32 asu32;
647b3bf60c7SK. Y. Srinivasan 	struct {
648b3bf60c7SK. Y. Srinivasan 		u32 id:24;
649b3bf60c7SK. Y. Srinivasan 		u32 reserved:8;
650b3bf60c7SK. Y. Srinivasan 	} u;
651b3bf60c7SK. Y. Srinivasan };
652b3bf60c7SK. Y. Srinivasan 
653509879bdSK. Y. Srinivasan enum hv_numa_policy {
654509879bdSK. Y. Srinivasan 	HV_BALANCED = 0,
655509879bdSK. Y. Srinivasan 	HV_LOCALIZED,
656509879bdSK. Y. Srinivasan };
657509879bdSK. Y. Srinivasan 
6587047f17dSK. Y. Srinivasan enum vmbus_device_type {
6597047f17dSK. Y. Srinivasan 	HV_IDE = 0,
6607047f17dSK. Y. Srinivasan 	HV_SCSI,
6617047f17dSK. Y. Srinivasan 	HV_FC,
6627047f17dSK. Y. Srinivasan 	HV_NIC,
6637047f17dSK. Y. Srinivasan 	HV_ND,
6647047f17dSK. Y. Srinivasan 	HV_PCIE,
6657047f17dSK. Y. Srinivasan 	HV_FB,
6667047f17dSK. Y. Srinivasan 	HV_KBD,
6677047f17dSK. Y. Srinivasan 	HV_MOUSE,
6687047f17dSK. Y. Srinivasan 	HV_KVP,
6697047f17dSK. Y. Srinivasan 	HV_TS,
6707047f17dSK. Y. Srinivasan 	HV_HB,
6717047f17dSK. Y. Srinivasan 	HV_SHUTDOWN,
6727047f17dSK. Y. Srinivasan 	HV_FCOPY,
6737047f17dSK. Y. Srinivasan 	HV_BACKUP,
6747047f17dSK. Y. Srinivasan 	HV_DM,
675f45be72cSHaiyang Zhang 	HV_UNKNOWN,
6767047f17dSK. Y. Srinivasan };
6777047f17dSK. Y. Srinivasan 
6787047f17dSK. Y. Srinivasan struct vmbus_device {
6797047f17dSK. Y. Srinivasan 	u16  dev_type;
6807047f17dSK. Y. Srinivasan 	uuid_le guid;
6817047f17dSK. Y. Srinivasan 	bool perf_device;
6827047f17dSK. Y. Srinivasan };
6837047f17dSK. Y. Srinivasan 
68446a97191SGreg Kroah-Hartman struct vmbus_channel {
68546a97191SGreg Kroah-Hartman 	struct list_head listentry;
68646a97191SGreg Kroah-Hartman 
68746a97191SGreg Kroah-Hartman 	struct hv_device *device_obj;
68846a97191SGreg Kroah-Hartman 
68946a97191SGreg Kroah-Hartman 	enum vmbus_channel_state state;
69046a97191SGreg Kroah-Hartman 
69146a97191SGreg Kroah-Hartman 	struct vmbus_channel_offer_channel offermsg;
69246a97191SGreg Kroah-Hartman 	/*
69346a97191SGreg Kroah-Hartman 	 * These are based on the OfferMsg.MonitorId.
69446a97191SGreg Kroah-Hartman 	 * Save it here for easy access.
69546a97191SGreg Kroah-Hartman 	 */
69646a97191SGreg Kroah-Hartman 	u8 monitor_grp;
69746a97191SGreg Kroah-Hartman 	u8 monitor_bit;
69846a97191SGreg Kroah-Hartman 
699c3582a2cSHaiyang Zhang 	bool rescind; /* got rescind msg */
7007fa32e5eSK. Y. Srinivasan 	struct completion rescind_event;
701c3582a2cSHaiyang Zhang 
70246a97191SGreg Kroah-Hartman 	u32 ringbuffer_gpadlhandle;
70346a97191SGreg Kroah-Hartman 
70446a97191SGreg Kroah-Hartman 	/* Allocated memory for ring buffer */
70546a97191SGreg Kroah-Hartman 	void *ringbuffer_pages;
70646a97191SGreg Kroah-Hartman 	u32 ringbuffer_pagecount;
70746a97191SGreg Kroah-Hartman 	struct hv_ring_buffer_info outbound;	/* send to parent */
70846a97191SGreg Kroah-Hartman 	struct hv_ring_buffer_info inbound;	/* receive from parent */
70946a97191SGreg Kroah-Hartman 
71046a97191SGreg Kroah-Hartman 	struct vmbus_close_msg close_msg;
71146a97191SGreg Kroah-Hartman 
7126981fbf3SStephen Hemminger 	/* Statistics */
7136981fbf3SStephen Hemminger 	u64	interrupts;	/* Host to Guest interrupts */
7146981fbf3SStephen Hemminger 	u64	sig_events;	/* Guest to Host events */
7156981fbf3SStephen Hemminger 
71651c6ce2aSStephen Hemminger 	/* Channel callback's invoked in softirq context */
717631e63a9SStephen Hemminger 	struct tasklet_struct callback_event;
71846a97191SGreg Kroah-Hartman 	void (*onchannel_callback)(void *context);
71946a97191SGreg Kroah-Hartman 	void *channel_callback_context;
720132368bdSK. Y. Srinivasan 
721132368bdSK. Y. Srinivasan 	/*
722b71e3282SStephen Hemminger 	 * A channel can be marked for one of three modes of reading:
723b71e3282SStephen Hemminger 	 *   BATCHED - callback called from taslket and should read
724b71e3282SStephen Hemminger 	 *            channel until empty. Interrupts from the host
725b71e3282SStephen Hemminger 	 *            are masked while read is in process (default).
726b71e3282SStephen Hemminger 	 *   DIRECT - callback called from tasklet (softirq).
727b71e3282SStephen Hemminger 	 *   ISR - callback called in interrupt context and must
728b71e3282SStephen Hemminger 	 *         invoke its own deferred processing.
729b71e3282SStephen Hemminger 	 *         Host interrupts are disabled and must be re-enabled
730b71e3282SStephen Hemminger 	 *         when ring is empty.
731132368bdSK. Y. Srinivasan 	 */
732b71e3282SStephen Hemminger 	enum hv_callback_mode {
733b71e3282SStephen Hemminger 		HV_CALL_BATCHED,
734b71e3282SStephen Hemminger 		HV_CALL_DIRECT,
735b71e3282SStephen Hemminger 		HV_CALL_ISR
736b71e3282SStephen Hemminger 	} callback_mode;
737b3bf60c7SK. Y. Srinivasan 
738b3bf60c7SK. Y. Srinivasan 	bool is_dedicated_interrupt;
73905784171SVitaly Kuznetsov 	u64 sig_event;
740abbf3b2aSK. Y. Srinivasan 
741abbf3b2aSK. Y. Srinivasan 	/*
742abbf3b2aSK. Y. Srinivasan 	 * Starting with win8, this field will be used to specify
743abbf3b2aSK. Y. Srinivasan 	 * the target virtual processor on which to deliver the interrupt for
744abbf3b2aSK. Y. Srinivasan 	 * the host to guest communication.
745abbf3b2aSK. Y. Srinivasan 	 * Prior to win8, incoming channel interrupts would only
746abbf3b2aSK. Y. Srinivasan 	 * be delivered on cpu 0. Setting this value to 0 would
747abbf3b2aSK. Y. Srinivasan 	 * preserve the earlier behavior.
748abbf3b2aSK. Y. Srinivasan 	 */
749abbf3b2aSK. Y. Srinivasan 	u32 target_vp;
750d3ba720dSK. Y. Srinivasan 	/* The corresponding CPUID in the guest */
751d3ba720dSK. Y. Srinivasan 	u32 target_cpu;
752e68d2971SK. Y. Srinivasan 	/*
7531f656ff3SK. Y. Srinivasan 	 * State to manage the CPU affiliation of channels.
7541f656ff3SK. Y. Srinivasan 	 */
7553b71107dSDexuan Cui 	struct cpumask alloced_cpus_in_node;
7561f656ff3SK. Y. Srinivasan 	int numa_node;
7571f656ff3SK. Y. Srinivasan 	/*
758e68d2971SK. Y. Srinivasan 	 * Support for sub-channels. For high performance devices,
759e68d2971SK. Y. Srinivasan 	 * it will be useful to have multiple sub-channels to support
760e68d2971SK. Y. Srinivasan 	 * a scalable communication infrastructure with the host.
761e68d2971SK. Y. Srinivasan 	 * The support for sub-channels is implemented as an extention
762e68d2971SK. Y. Srinivasan 	 * to the current infrastructure.
763e68d2971SK. Y. Srinivasan 	 * The initial offer is considered the primary channel and this
764e68d2971SK. Y. Srinivasan 	 * offer message will indicate if the host supports sub-channels.
765e68d2971SK. Y. Srinivasan 	 * The guest is free to ask for sub-channels to be offerred and can
766e68d2971SK. Y. Srinivasan 	 * open these sub-channels as a normal "primary" channel. However,
767e68d2971SK. Y. Srinivasan 	 * all sub-channels will have the same type and instance guids as the
768e68d2971SK. Y. Srinivasan 	 * primary channel. Requests sent on a given channel will result in a
769e68d2971SK. Y. Srinivasan 	 * response on the same channel.
770e68d2971SK. Y. Srinivasan 	 */
771e68d2971SK. Y. Srinivasan 
772e68d2971SK. Y. Srinivasan 	/*
773e68d2971SK. Y. Srinivasan 	 * Sub-channel creation callback. This callback will be called in
774e68d2971SK. Y. Srinivasan 	 * process context when a sub-channel offer is received from the host.
775e68d2971SK. Y. Srinivasan 	 * The guest can open the sub-channel in the context of this callback.
776e68d2971SK. Y. Srinivasan 	 */
777e68d2971SK. Y. Srinivasan 	void (*sc_creation_callback)(struct vmbus_channel *new_sc);
778e68d2971SK. Y. Srinivasan 
77967fae053SVitaly Kuznetsov 	/*
780499e8401SDexuan Cui 	 * Channel rescind callback. Some channels (the hvsock ones), need to
781499e8401SDexuan Cui 	 * register a callback which is invoked in vmbus_onoffer_rescind().
782499e8401SDexuan Cui 	 */
783499e8401SDexuan Cui 	void (*chn_rescind_callback)(struct vmbus_channel *channel);
784499e8401SDexuan Cui 
785499e8401SDexuan Cui 	/*
78667fae053SVitaly Kuznetsov 	 * The spinlock to protect the structure. It is being used to protect
78767fae053SVitaly Kuznetsov 	 * test-and-set access to various attributes of the structure as well
78867fae053SVitaly Kuznetsov 	 * as all sc_list operations.
78967fae053SVitaly Kuznetsov 	 */
79067fae053SVitaly Kuznetsov 	spinlock_t lock;
791e68d2971SK. Y. Srinivasan 	/*
792e68d2971SK. Y. Srinivasan 	 * All Sub-channels of a primary channel are linked here.
793e68d2971SK. Y. Srinivasan 	 */
794e68d2971SK. Y. Srinivasan 	struct list_head sc_list;
795e68d2971SK. Y. Srinivasan 	/*
796fea844a2SVitaly Kuznetsov 	 * Current number of sub-channels.
797fea844a2SVitaly Kuznetsov 	 */
798fea844a2SVitaly Kuznetsov 	int num_sc;
799fea844a2SVitaly Kuznetsov 	/*
800fea844a2SVitaly Kuznetsov 	 * Number of a sub-channel (position within sc_list) which is supposed
801fea844a2SVitaly Kuznetsov 	 * to be used as the next outgoing channel.
802fea844a2SVitaly Kuznetsov 	 */
803fea844a2SVitaly Kuznetsov 	int next_oc;
804fea844a2SVitaly Kuznetsov 	/*
805e68d2971SK. Y. Srinivasan 	 * The primary channel this sub-channel belongs to.
806e68d2971SK. Y. Srinivasan 	 * This will be NULL for the primary channel.
807e68d2971SK. Y. Srinivasan 	 */
808e68d2971SK. Y. Srinivasan 	struct vmbus_channel *primary_channel;
8098a7206a8SK. Y. Srinivasan 	/*
8108a7206a8SK. Y. Srinivasan 	 * Support per-channel state for use by vmbus drivers.
8118a7206a8SK. Y. Srinivasan 	 */
8128a7206a8SK. Y. Srinivasan 	void *per_channel_state;
8133a28fa35SK. Y. Srinivasan 	/*
8143a28fa35SK. Y. Srinivasan 	 * To support per-cpu lookup mapping of relid to channel,
8153a28fa35SK. Y. Srinivasan 	 * link up channels based on their CPU affinity.
8163a28fa35SK. Y. Srinivasan 	 */
8173a28fa35SK. Y. Srinivasan 	struct list_head percpu_list;
8188200f208SStephen Hemminger 
8198200f208SStephen Hemminger 	/*
8208200f208SStephen Hemminger 	 * Defer freeing channel until after all cpu's have
8218200f208SStephen Hemminger 	 * gone through grace period.
8228200f208SStephen Hemminger 	 */
8238200f208SStephen Hemminger 	struct rcu_head rcu;
8248200f208SStephen Hemminger 
8258599846dSK. Y. Srinivasan 	/*
826c2e5df61SStephen Hemminger 	 * For sysfs per-channel properties.
827c2e5df61SStephen Hemminger 	 */
828c2e5df61SStephen Hemminger 	struct kobject			kobj;
829c2e5df61SStephen Hemminger 
830c2e5df61SStephen Hemminger 	/*
8313724287cSK. Y. Srinivasan 	 * For performance critical channels (storage, networking
8323724287cSK. Y. Srinivasan 	 * etc,), Hyper-V has a mechanism to enhance the throughput
8333724287cSK. Y. Srinivasan 	 * at the expense of latency:
8343724287cSK. Y. Srinivasan 	 * When the host is to be signaled, we just set a bit in a shared page
8353724287cSK. Y. Srinivasan 	 * and this bit will be inspected by the hypervisor within a certain
8363724287cSK. Y. Srinivasan 	 * window and if the bit is set, the host will be signaled. The window
8373724287cSK. Y. Srinivasan 	 * of time is the monitor latency - currently around 100 usecs. This
8383724287cSK. Y. Srinivasan 	 * mechanism improves throughput by:
8393724287cSK. Y. Srinivasan 	 *
8403724287cSK. Y. Srinivasan 	 * A) Making the host more efficient - each time it wakes up,
8413724287cSK. Y. Srinivasan 	 *    potentially it will process morev number of packets. The
8423724287cSK. Y. Srinivasan 	 *    monitor latency allows a batch to build up.
8433724287cSK. Y. Srinivasan 	 * B) By deferring the hypercall to signal, we will also minimize
8443724287cSK. Y. Srinivasan 	 *    the interrupts.
8453724287cSK. Y. Srinivasan 	 *
8463724287cSK. Y. Srinivasan 	 * Clearly, these optimizations improve throughput at the expense of
8473724287cSK. Y. Srinivasan 	 * latency. Furthermore, since the channel is shared for both
8483724287cSK. Y. Srinivasan 	 * control and data messages, control messages currently suffer
8493724287cSK. Y. Srinivasan 	 * unnecessary latency adversley impacting performance and boot
8503724287cSK. Y. Srinivasan 	 * time. To fix this issue, permit tagging the channel as being
8513724287cSK. Y. Srinivasan 	 * in "low latency" mode. In this mode, we will bypass the monitor
8523724287cSK. Y. Srinivasan 	 * mechanism.
8533724287cSK. Y. Srinivasan 	 */
8543724287cSK. Y. Srinivasan 	bool low_latency;
855fe760e4dSK. Y. Srinivasan 
856509879bdSK. Y. Srinivasan 	/*
857509879bdSK. Y. Srinivasan 	 * NUMA distribution policy:
858ce767047SHaiyang Zhang 	 * We support two policies:
859509879bdSK. Y. Srinivasan 	 * 1) Balanced: Here all performance critical channels are
860509879bdSK. Y. Srinivasan 	 *    distributed evenly amongst all the NUMA nodes.
861509879bdSK. Y. Srinivasan 	 *    This policy will be the default policy.
862509879bdSK. Y. Srinivasan 	 * 2) Localized: All channels of a given instance of a
863509879bdSK. Y. Srinivasan 	 *    performance critical service will be assigned CPUs
864509879bdSK. Y. Srinivasan 	 *    within a selected NUMA node.
865509879bdSK. Y. Srinivasan 	 */
866509879bdSK. Y. Srinivasan 	enum hv_numa_policy affinity_policy;
867509879bdSK. Y. Srinivasan 
8686f3d791fSK. Y. Srinivasan 	bool probe_done;
8696f3d791fSK. Y. Srinivasan 
87046a97191SGreg Kroah-Hartman };
87146a97191SGreg Kroah-Hartman 
872e8d6ca02SDexuan Cui static inline bool is_hvsock_channel(const struct vmbus_channel *c)
873e8d6ca02SDexuan Cui {
874e8d6ca02SDexuan Cui 	return !!(c->offermsg.offer.chn_flags &
875e8d6ca02SDexuan Cui 		  VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER);
876e8d6ca02SDexuan Cui }
877e8d6ca02SDexuan Cui 
878509879bdSK. Y. Srinivasan static inline void set_channel_affinity_state(struct vmbus_channel *c,
879509879bdSK. Y. Srinivasan 					      enum hv_numa_policy policy)
880509879bdSK. Y. Srinivasan {
881509879bdSK. Y. Srinivasan 	c->affinity_policy = policy;
882509879bdSK. Y. Srinivasan }
883509879bdSK. Y. Srinivasan 
884b71e3282SStephen Hemminger static inline void set_channel_read_mode(struct vmbus_channel *c,
885b71e3282SStephen Hemminger 					enum hv_callback_mode mode)
886132368bdSK. Y. Srinivasan {
887b71e3282SStephen Hemminger 	c->callback_mode = mode;
888132368bdSK. Y. Srinivasan }
889132368bdSK. Y. Srinivasan 
8908a7206a8SK. Y. Srinivasan static inline void set_per_channel_state(struct vmbus_channel *c, void *s)
8918a7206a8SK. Y. Srinivasan {
8928a7206a8SK. Y. Srinivasan 	c->per_channel_state = s;
8938a7206a8SK. Y. Srinivasan }
8948a7206a8SK. Y. Srinivasan 
8958a7206a8SK. Y. Srinivasan static inline void *get_per_channel_state(struct vmbus_channel *c)
8968a7206a8SK. Y. Srinivasan {
8978a7206a8SK. Y. Srinivasan 	return c->per_channel_state;
8988a7206a8SK. Y. Srinivasan }
8998a7206a8SK. Y. Srinivasan 
9003c75354dSDexuan Cui static inline void set_channel_pending_send_size(struct vmbus_channel *c,
9013c75354dSDexuan Cui 						 u32 size)
9023c75354dSDexuan Cui {
9033c75354dSDexuan Cui 	c->outbound.ring_buffer->pending_send_sz = size;
9043c75354dSDexuan Cui }
9053c75354dSDexuan Cui 
9063724287cSK. Y. Srinivasan static inline void set_low_latency_mode(struct vmbus_channel *c)
9073724287cSK. Y. Srinivasan {
9083724287cSK. Y. Srinivasan 	c->low_latency = true;
9093724287cSK. Y. Srinivasan }
9103724287cSK. Y. Srinivasan 
9113724287cSK. Y. Srinivasan static inline void clear_low_latency_mode(struct vmbus_channel *c)
9123724287cSK. Y. Srinivasan {
9133724287cSK. Y. Srinivasan 	c->low_latency = false;
9143724287cSK. Y. Srinivasan }
9153724287cSK. Y. Srinivasan 
91646a97191SGreg Kroah-Hartman void vmbus_onmessage(void *context);
91746a97191SGreg Kroah-Hartman 
91846a97191SGreg Kroah-Hartman int vmbus_request_offers(void);
91946a97191SGreg Kroah-Hartman 
920e68d2971SK. Y. Srinivasan /*
921e68d2971SK. Y. Srinivasan  * APIs for managing sub-channels.
922e68d2971SK. Y. Srinivasan  */
923e68d2971SK. Y. Srinivasan 
924e68d2971SK. Y. Srinivasan void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
925e68d2971SK. Y. Srinivasan 			void (*sc_cr_cb)(struct vmbus_channel *new_sc));
926e68d2971SK. Y. Srinivasan 
927499e8401SDexuan Cui void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
928499e8401SDexuan Cui 		void (*chn_rescind_cb)(struct vmbus_channel *));
929499e8401SDexuan Cui 
930e68d2971SK. Y. Srinivasan /*
931e68d2971SK. Y. Srinivasan  * Retrieve the (sub) channel on which to send an outgoing request.
932e68d2971SK. Y. Srinivasan  * When a primary channel has multiple sub-channels, we choose a
933e68d2971SK. Y. Srinivasan  * channel whose VCPU binding is closest to the VCPU on which
934e68d2971SK. Y. Srinivasan  * this call is being made.
935e68d2971SK. Y. Srinivasan  */
936e68d2971SK. Y. Srinivasan struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary);
937e68d2971SK. Y. Srinivasan 
938e68d2971SK. Y. Srinivasan /*
939e68d2971SK. Y. Srinivasan  * Check if sub-channels have already been offerred. This API will be useful
940e68d2971SK. Y. Srinivasan  * when the driver is unloaded after establishing sub-channels. In this case,
941e68d2971SK. Y. Srinivasan  * when the driver is re-loaded, the driver would have to check if the
942e68d2971SK. Y. Srinivasan  * subchannels have already been established before attempting to request
943e68d2971SK. Y. Srinivasan  * the creation of sub-channels.
944e68d2971SK. Y. Srinivasan  * This function returns TRUE to indicate that subchannels have already been
945e68d2971SK. Y. Srinivasan  * created.
946e68d2971SK. Y. Srinivasan  * This function should be invoked after setting the callback function for
947e68d2971SK. Y. Srinivasan  * sub-channel creation.
948e68d2971SK. Y. Srinivasan  */
949e68d2971SK. Y. Srinivasan bool vmbus_are_subchannels_present(struct vmbus_channel *primary);
950e68d2971SK. Y. Srinivasan 
95146a97191SGreg Kroah-Hartman /* The format must be the same as struct vmdata_gpa_direct */
95246a97191SGreg Kroah-Hartman struct vmbus_channel_packet_page_buffer {
95346a97191SGreg Kroah-Hartman 	u16 type;
95446a97191SGreg Kroah-Hartman 	u16 dataoffset8;
95546a97191SGreg Kroah-Hartman 	u16 length8;
95646a97191SGreg Kroah-Hartman 	u16 flags;
95746a97191SGreg Kroah-Hartman 	u64 transactionid;
95846a97191SGreg Kroah-Hartman 	u32 reserved;
95946a97191SGreg Kroah-Hartman 	u32 rangecount;
96046a97191SGreg Kroah-Hartman 	struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT];
96146a97191SGreg Kroah-Hartman } __packed;
96246a97191SGreg Kroah-Hartman 
96346a97191SGreg Kroah-Hartman /* The format must be the same as struct vmdata_gpa_direct */
96446a97191SGreg Kroah-Hartman struct vmbus_channel_packet_multipage_buffer {
96546a97191SGreg Kroah-Hartman 	u16 type;
96646a97191SGreg Kroah-Hartman 	u16 dataoffset8;
96746a97191SGreg Kroah-Hartman 	u16 length8;
96846a97191SGreg Kroah-Hartman 	u16 flags;
96946a97191SGreg Kroah-Hartman 	u64 transactionid;
97046a97191SGreg Kroah-Hartman 	u32 reserved;
97146a97191SGreg Kroah-Hartman 	u32 rangecount;		/* Always 1 in this case */
97246a97191SGreg Kroah-Hartman 	struct hv_multipage_buffer range;
97346a97191SGreg Kroah-Hartman } __packed;
97446a97191SGreg Kroah-Hartman 
975d61031eeSK. Y. Srinivasan /* The format must be the same as struct vmdata_gpa_direct */
976d61031eeSK. Y. Srinivasan struct vmbus_packet_mpb_array {
977d61031eeSK. Y. Srinivasan 	u16 type;
978d61031eeSK. Y. Srinivasan 	u16 dataoffset8;
979d61031eeSK. Y. Srinivasan 	u16 length8;
980d61031eeSK. Y. Srinivasan 	u16 flags;
981d61031eeSK. Y. Srinivasan 	u64 transactionid;
982d61031eeSK. Y. Srinivasan 	u32 reserved;
983d61031eeSK. Y. Srinivasan 	u32 rangecount;         /* Always 1 in this case */
984d61031eeSK. Y. Srinivasan 	struct hv_mpb_array range;
985d61031eeSK. Y. Srinivasan } __packed;
986d61031eeSK. Y. Srinivasan 
98746a97191SGreg Kroah-Hartman 
98846a97191SGreg Kroah-Hartman extern int vmbus_open(struct vmbus_channel *channel,
98946a97191SGreg Kroah-Hartman 			    u32 send_ringbuffersize,
99046a97191SGreg Kroah-Hartman 			    u32 recv_ringbuffersize,
99146a97191SGreg Kroah-Hartman 			    void *userdata,
99246a97191SGreg Kroah-Hartman 			    u32 userdatalen,
99346a97191SGreg Kroah-Hartman 			    void (*onchannel_callback)(void *context),
99446a97191SGreg Kroah-Hartman 			    void *context);
99546a97191SGreg Kroah-Hartman 
99646a97191SGreg Kroah-Hartman extern void vmbus_close(struct vmbus_channel *channel);
99746a97191SGreg Kroah-Hartman 
99846a97191SGreg Kroah-Hartman extern int vmbus_sendpacket(struct vmbus_channel *channel,
999011a7c3cSK. Y. Srinivasan 				  void *buffer,
100046a97191SGreg Kroah-Hartman 				  u32 bufferLen,
100146a97191SGreg Kroah-Hartman 				  u64 requestid,
100246a97191SGreg Kroah-Hartman 				  enum vmbus_packet_type type,
100346a97191SGreg Kroah-Hartman 				  u32 flags);
100446a97191SGreg Kroah-Hartman 
100546a97191SGreg Kroah-Hartman extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
100646a97191SGreg Kroah-Hartman 					    struct hv_page_buffer pagebuffers[],
100746a97191SGreg Kroah-Hartman 					    u32 pagecount,
100846a97191SGreg Kroah-Hartman 					    void *buffer,
100946a97191SGreg Kroah-Hartman 					    u32 bufferlen,
101046a97191SGreg Kroah-Hartman 					    u64 requestid);
101146a97191SGreg Kroah-Hartman 
1012d61031eeSK. Y. Srinivasan extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
1013d61031eeSK. Y. Srinivasan 				     struct vmbus_packet_mpb_array *mpb,
1014d61031eeSK. Y. Srinivasan 				     u32 desc_size,
1015d61031eeSK. Y. Srinivasan 				     void *buffer,
1016d61031eeSK. Y. Srinivasan 				     u32 bufferlen,
1017d61031eeSK. Y. Srinivasan 				     u64 requestid);
1018d61031eeSK. Y. Srinivasan 
101946a97191SGreg Kroah-Hartman extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
102046a97191SGreg Kroah-Hartman 				      void *kbuffer,
102146a97191SGreg Kroah-Hartman 				      u32 size,
102246a97191SGreg Kroah-Hartman 				      u32 *gpadl_handle);
102346a97191SGreg Kroah-Hartman 
102446a97191SGreg Kroah-Hartman extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
102546a97191SGreg Kroah-Hartman 				     u32 gpadl_handle);
102646a97191SGreg Kroah-Hartman 
102746a97191SGreg Kroah-Hartman extern int vmbus_recvpacket(struct vmbus_channel *channel,
102846a97191SGreg Kroah-Hartman 				  void *buffer,
102946a97191SGreg Kroah-Hartman 				  u32 bufferlen,
103046a97191SGreg Kroah-Hartman 				  u32 *buffer_actual_len,
103146a97191SGreg Kroah-Hartman 				  u64 *requestid);
103246a97191SGreg Kroah-Hartman 
103346a97191SGreg Kroah-Hartman extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
103446a97191SGreg Kroah-Hartman 				     void *buffer,
103546a97191SGreg Kroah-Hartman 				     u32 bufferlen,
103646a97191SGreg Kroah-Hartman 				     u32 *buffer_actual_len,
103746a97191SGreg Kroah-Hartman 				     u64 *requestid);
103846a97191SGreg Kroah-Hartman 
103946a97191SGreg Kroah-Hartman 
104046a97191SGreg Kroah-Hartman extern void vmbus_ontimer(unsigned long data);
104146a97191SGreg Kroah-Hartman 
104246a97191SGreg Kroah-Hartman /* Base driver object */
104346a97191SGreg Kroah-Hartman struct hv_driver {
104446a97191SGreg Kroah-Hartman 	const char *name;
104546a97191SGreg Kroah-Hartman 
10468981da32SDexuan Cui 	/*
10478981da32SDexuan Cui 	 * A hvsock offer, which has a VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER
10488981da32SDexuan Cui 	 * channel flag, actually doesn't mean a synthetic device because the
10498981da32SDexuan Cui 	 * offer's if_type/if_instance can change for every new hvsock
10508981da32SDexuan Cui 	 * connection.
10518981da32SDexuan Cui 	 *
10528981da32SDexuan Cui 	 * However, to facilitate the notification of new-offer/rescind-offer
10538981da32SDexuan Cui 	 * from vmbus driver to hvsock driver, we can handle hvsock offer as
10548981da32SDexuan Cui 	 * a special vmbus device, and hence we need the below flag to
10558981da32SDexuan Cui 	 * indicate if the driver is the hvsock driver or not: we need to
10568981da32SDexuan Cui 	 * specially treat the hvosck offer & driver in vmbus_match().
10578981da32SDexuan Cui 	 */
10588981da32SDexuan Cui 	bool hvsock;
10598981da32SDexuan Cui 
106046a97191SGreg Kroah-Hartman 	/* the device type supported by this driver */
106146a97191SGreg Kroah-Hartman 	uuid_le dev_type;
106246a97191SGreg Kroah-Hartman 	const struct hv_vmbus_device_id *id_table;
106346a97191SGreg Kroah-Hartman 
106446a97191SGreg Kroah-Hartman 	struct device_driver driver;
106546a97191SGreg Kroah-Hartman 
1066fc76936dSStephen Hemminger 	/* dynamic device GUID's */
1067fc76936dSStephen Hemminger 	struct  {
1068fc76936dSStephen Hemminger 		spinlock_t lock;
1069fc76936dSStephen Hemminger 		struct list_head list;
1070fc76936dSStephen Hemminger 	} dynids;
1071fc76936dSStephen Hemminger 
107246a97191SGreg Kroah-Hartman 	int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *);
107346a97191SGreg Kroah-Hartman 	int (*remove)(struct hv_device *);
107446a97191SGreg Kroah-Hartman 	void (*shutdown)(struct hv_device *);
107546a97191SGreg Kroah-Hartman 
107646a97191SGreg Kroah-Hartman };
107746a97191SGreg Kroah-Hartman 
107846a97191SGreg Kroah-Hartman /* Base device object */
107946a97191SGreg Kroah-Hartman struct hv_device {
108046a97191SGreg Kroah-Hartman 	/* the device type id of this device */
108146a97191SGreg Kroah-Hartman 	uuid_le dev_type;
108246a97191SGreg Kroah-Hartman 
108346a97191SGreg Kroah-Hartman 	/* the device instance id of this device */
108446a97191SGreg Kroah-Hartman 	uuid_le dev_instance;
10857047f17dSK. Y. Srinivasan 	u16 vendor_id;
10867047f17dSK. Y. Srinivasan 	u16 device_id;
108746a97191SGreg Kroah-Hartman 
108846a97191SGreg Kroah-Hartman 	struct device device;
108946a97191SGreg Kroah-Hartman 
109046a97191SGreg Kroah-Hartman 	struct vmbus_channel *channel;
1091c2e5df61SStephen Hemminger 	struct kset	     *channels_kset;
109246a97191SGreg Kroah-Hartman };
109346a97191SGreg Kroah-Hartman 
109446a97191SGreg Kroah-Hartman 
109546a97191SGreg Kroah-Hartman static inline struct hv_device *device_to_hv_device(struct device *d)
109646a97191SGreg Kroah-Hartman {
109746a97191SGreg Kroah-Hartman 	return container_of(d, struct hv_device, device);
109846a97191SGreg Kroah-Hartman }
109946a97191SGreg Kroah-Hartman 
110046a97191SGreg Kroah-Hartman static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
110146a97191SGreg Kroah-Hartman {
110246a97191SGreg Kroah-Hartman 	return container_of(d, struct hv_driver, driver);
110346a97191SGreg Kroah-Hartman }
110446a97191SGreg Kroah-Hartman 
110546a97191SGreg Kroah-Hartman static inline void hv_set_drvdata(struct hv_device *dev, void *data)
110646a97191SGreg Kroah-Hartman {
110746a97191SGreg Kroah-Hartman 	dev_set_drvdata(&dev->device, data);
110846a97191SGreg Kroah-Hartman }
110946a97191SGreg Kroah-Hartman 
111046a97191SGreg Kroah-Hartman static inline void *hv_get_drvdata(struct hv_device *dev)
111146a97191SGreg Kroah-Hartman {
111246a97191SGreg Kroah-Hartman 	return dev_get_drvdata(&dev->device);
111346a97191SGreg Kroah-Hartman }
111446a97191SGreg Kroah-Hartman 
11154827ee1dSStephen Hemminger struct hv_ring_buffer_debug_info {
11164827ee1dSStephen Hemminger 	u32 current_interrupt_mask;
11174827ee1dSStephen Hemminger 	u32 current_read_index;
11184827ee1dSStephen Hemminger 	u32 current_write_index;
11194827ee1dSStephen Hemminger 	u32 bytes_avail_toread;
11204827ee1dSStephen Hemminger 	u32 bytes_avail_towrite;
11214827ee1dSStephen Hemminger };
11224827ee1dSStephen Hemminger 
11234827ee1dSStephen Hemminger void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
11244827ee1dSStephen Hemminger 			    struct hv_ring_buffer_debug_info *debug_info);
11254827ee1dSStephen Hemminger 
112646a97191SGreg Kroah-Hartman /* Vmbus interface */
112746a97191SGreg Kroah-Hartman #define vmbus_driver_register(driver)	\
112846a97191SGreg Kroah-Hartman 	__vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
112946a97191SGreg Kroah-Hartman int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
113046a97191SGreg Kroah-Hartman 					 struct module *owner,
113146a97191SGreg Kroah-Hartman 					 const char *mod_name);
113246a97191SGreg Kroah-Hartman void vmbus_driver_unregister(struct hv_driver *hv_driver);
113346a97191SGreg Kroah-Hartman 
113485d9aa70SDexuan Cui void vmbus_hvsock_device_unregister(struct vmbus_channel *channel);
113585d9aa70SDexuan Cui 
113635464483SJake Oshins int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
113735464483SJake Oshins 			resource_size_t min, resource_size_t max,
113835464483SJake Oshins 			resource_size_t size, resource_size_t align,
113935464483SJake Oshins 			bool fb_overlap_ok);
114097fb77dcSJake Oshins void vmbus_free_mmio(resource_size_t start, resource_size_t size);
1141619848bdSJake Oshins 
114246a97191SGreg Kroah-Hartman /*
11437fb96565SK. Y. Srinivasan  * GUID definitions of various offer types - services offered to the guest.
11447fb96565SK. Y. Srinivasan  */
11457fb96565SK. Y. Srinivasan 
11467fb96565SK. Y. Srinivasan /*
11477fb96565SK. Y. Srinivasan  * Network GUID
11487fb96565SK. Y. Srinivasan  * {f8615163-df3e-46c5-913f-f2d2f965ed0e}
11497fb96565SK. Y. Srinivasan  */
11507fb96565SK. Y. Srinivasan #define HV_NIC_GUID \
1151af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xf8615163, 0xdf3e, 0x46c5, 0x91, 0x3f, \
1152af3ff643SK. Y. Srinivasan 			0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e)
11537fb96565SK. Y. Srinivasan 
11547fb96565SK. Y. Srinivasan /*
11557fb96565SK. Y. Srinivasan  * IDE GUID
11567fb96565SK. Y. Srinivasan  * {32412632-86cb-44a2-9b5c-50d1417354f5}
11577fb96565SK. Y. Srinivasan  */
11587fb96565SK. Y. Srinivasan #define HV_IDE_GUID \
1159af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x32412632, 0x86cb, 0x44a2, 0x9b, 0x5c, \
1160af3ff643SK. Y. Srinivasan 			0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5)
11617fb96565SK. Y. Srinivasan 
11627fb96565SK. Y. Srinivasan /*
11637fb96565SK. Y. Srinivasan  * SCSI GUID
11647fb96565SK. Y. Srinivasan  * {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
11657fb96565SK. Y. Srinivasan  */
11667fb96565SK. Y. Srinivasan #define HV_SCSI_GUID \
1167af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xba6163d9, 0x04a1, 0x4d29, 0xb6, 0x05, \
1168af3ff643SK. Y. Srinivasan 			0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f)
11697fb96565SK. Y. Srinivasan 
11707fb96565SK. Y. Srinivasan /*
11717fb96565SK. Y. Srinivasan  * Shutdown GUID
11727fb96565SK. Y. Srinivasan  * {0e0b6031-5213-4934-818b-38d90ced39db}
11737fb96565SK. Y. Srinivasan  */
11747fb96565SK. Y. Srinivasan #define HV_SHUTDOWN_GUID \
1175af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x0e0b6031, 0x5213, 0x4934, 0x81, 0x8b, \
1176af3ff643SK. Y. Srinivasan 			0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb)
11777fb96565SK. Y. Srinivasan 
11787fb96565SK. Y. Srinivasan /*
11797fb96565SK. Y. Srinivasan  * Time Synch GUID
11807fb96565SK. Y. Srinivasan  * {9527E630-D0AE-497b-ADCE-E80AB0175CAF}
11817fb96565SK. Y. Srinivasan  */
11827fb96565SK. Y. Srinivasan #define HV_TS_GUID \
1183af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x9527e630, 0xd0ae, 0x497b, 0xad, 0xce, \
1184af3ff643SK. Y. Srinivasan 			0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
11857fb96565SK. Y. Srinivasan 
11867fb96565SK. Y. Srinivasan /*
11877fb96565SK. Y. Srinivasan  * Heartbeat GUID
11887fb96565SK. Y. Srinivasan  * {57164f39-9115-4e78-ab55-382f3bd5422d}
11897fb96565SK. Y. Srinivasan  */
11907fb96565SK. Y. Srinivasan #define HV_HEART_BEAT_GUID \
1191af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, \
1192af3ff643SK. Y. Srinivasan 			0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
11937fb96565SK. Y. Srinivasan 
11947fb96565SK. Y. Srinivasan /*
11957fb96565SK. Y. Srinivasan  * KVP GUID
11967fb96565SK. Y. Srinivasan  * {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}
11977fb96565SK. Y. Srinivasan  */
11987fb96565SK. Y. Srinivasan #define HV_KVP_GUID \
1199af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xa9a0f4e7, 0x5a45, 0x4d96, 0xb8, 0x27, \
1200af3ff643SK. Y. Srinivasan 			0x8a, 0x84, 0x1e, 0x8c, 0x03, 0xe6)
12017fb96565SK. Y. Srinivasan 
12027fb96565SK. Y. Srinivasan /*
12037fb96565SK. Y. Srinivasan  * Dynamic memory GUID
12047fb96565SK. Y. Srinivasan  * {525074dc-8985-46e2-8057-a307dc18a502}
12057fb96565SK. Y. Srinivasan  */
12067fb96565SK. Y. Srinivasan #define HV_DM_GUID \
1207af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x525074dc, 0x8985, 0x46e2, 0x80, 0x57, \
1208af3ff643SK. Y. Srinivasan 			0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02)
12097fb96565SK. Y. Srinivasan 
12107fb96565SK. Y. Srinivasan /*
12117fb96565SK. Y. Srinivasan  * Mouse GUID
12127fb96565SK. Y. Srinivasan  * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}
12137fb96565SK. Y. Srinivasan  */
12147fb96565SK. Y. Srinivasan #define HV_MOUSE_GUID \
1215af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xcfa8b69e, 0x5b4a, 0x4cc0, 0xb9, 0x8b, \
1216af3ff643SK. Y. Srinivasan 			0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a)
12177fb96565SK. Y. Srinivasan 
12187fb96565SK. Y. Srinivasan /*
12192048157aSDexuan Cui  * Keyboard GUID
12202048157aSDexuan Cui  * {f912ad6d-2b17-48ea-bd65-f927a61c7684}
12212048157aSDexuan Cui  */
12222048157aSDexuan Cui #define HV_KBD_GUID \
12232048157aSDexuan Cui 	.guid = UUID_LE(0xf912ad6d, 0x2b17, 0x48ea, 0xbd, 0x65, \
12242048157aSDexuan Cui 			0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84)
12252048157aSDexuan Cui 
12262048157aSDexuan Cui /*
122796dd86faSK. Y. Srinivasan  * VSS (Backup/Restore) GUID
122896dd86faSK. Y. Srinivasan  */
122996dd86faSK. Y. Srinivasan #define HV_VSS_GUID \
1230af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x35fa2e29, 0xea23, 0x4236, 0x96, 0xae, \
1231af3ff643SK. Y. Srinivasan 			0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40)
123296dd86faSK. Y. Srinivasan /*
123368a2d20bSHaiyang Zhang  * Synthetic Video GUID
123468a2d20bSHaiyang Zhang  * {DA0A7802-E377-4aac-8E77-0558EB1073F8}
123568a2d20bSHaiyang Zhang  */
123668a2d20bSHaiyang Zhang #define HV_SYNTHVID_GUID \
1237af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xda0a7802, 0xe377, 0x4aac, 0x8e, 0x77, \
1238af3ff643SK. Y. Srinivasan 			0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8)
123968a2d20bSHaiyang Zhang 
124068a2d20bSHaiyang Zhang /*
124198b80d89SK. Y. Srinivasan  * Synthetic FC GUID
124298b80d89SK. Y. Srinivasan  * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda}
124398b80d89SK. Y. Srinivasan  */
124498b80d89SK. Y. Srinivasan #define HV_SYNTHFC_GUID \
1245af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x2f9bcc4a, 0x0069, 0x4af3, 0xb7, 0x6b, \
1246af3ff643SK. Y. Srinivasan 			0x6f, 0xd0, 0xbe, 0x52, 0x8c, 0xda)
124798b80d89SK. Y. Srinivasan 
124898b80d89SK. Y. Srinivasan /*
124901325476SK. Y. Srinivasan  * Guest File Copy Service
125001325476SK. Y. Srinivasan  * {34D14BE3-DEE4-41c8-9AE7-6B174977C192}
125101325476SK. Y. Srinivasan  */
125201325476SK. Y. Srinivasan 
125301325476SK. Y. Srinivasan #define HV_FCOPY_GUID \
1254af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x34d14be3, 0xdee4, 0x41c8, 0x9a, 0xe7, \
1255af3ff643SK. Y. Srinivasan 			0x6b, 0x17, 0x49, 0x77, 0xc1, 0x92)
125601325476SK. Y. Srinivasan 
125701325476SK. Y. Srinivasan /*
125804653a00SK. Y. Srinivasan  * NetworkDirect. This is the guest RDMA service.
125904653a00SK. Y. Srinivasan  * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}
126004653a00SK. Y. Srinivasan  */
126104653a00SK. Y. Srinivasan #define HV_ND_GUID \
1262af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x8c2eaf3d, 0x32a7, 0x4b09, 0xab, 0x99, \
1263af3ff643SK. Y. Srinivasan 			0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01)
126404653a00SK. Y. Srinivasan 
126504653a00SK. Y. Srinivasan /*
12663053c762SJake Oshins  * PCI Express Pass Through
12673053c762SJake Oshins  * {44C4F61D-4444-4400-9D52-802E27EDE19F}
12683053c762SJake Oshins  */
12693053c762SJake Oshins 
12703053c762SJake Oshins #define HV_PCIE_GUID \
1271af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x44c4f61d, 0x4444, 0x4400, 0x9d, 0x52, \
1272af3ff643SK. Y. Srinivasan 			0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f)
12733053c762SJake Oshins 
12743053c762SJake Oshins /*
12750f98829aSDexuan Cui  * Linux doesn't support the 3 devices: the first two are for
12760f98829aSDexuan Cui  * Automatic Virtual Machine Activation, and the third is for
12770f98829aSDexuan Cui  * Remote Desktop Virtualization.
12780f98829aSDexuan Cui  * {f8e65716-3cb3-4a06-9a60-1889c5cccab5}
12790f98829aSDexuan Cui  * {3375baf4-9e15-4b30-b765-67acb10d607b}
12800f98829aSDexuan Cui  * {276aacf4-ac15-426c-98dd-7521ad3f01fe}
12810f98829aSDexuan Cui  */
12820f98829aSDexuan Cui 
12830f98829aSDexuan Cui #define HV_AVMA1_GUID \
12840f98829aSDexuan Cui 	.guid = UUID_LE(0xf8e65716, 0x3cb3, 0x4a06, 0x9a, 0x60, \
12850f98829aSDexuan Cui 			0x18, 0x89, 0xc5, 0xcc, 0xca, 0xb5)
12860f98829aSDexuan Cui 
12870f98829aSDexuan Cui #define HV_AVMA2_GUID \
12880f98829aSDexuan Cui 	.guid = UUID_LE(0x3375baf4, 0x9e15, 0x4b30, 0xb7, 0x65, \
12890f98829aSDexuan Cui 			0x67, 0xac, 0xb1, 0x0d, 0x60, 0x7b)
12900f98829aSDexuan Cui 
12910f98829aSDexuan Cui #define HV_RDV_GUID \
12920f98829aSDexuan Cui 	.guid = UUID_LE(0x276aacf4, 0xac15, 0x426c, 0x98, 0xdd, \
12930f98829aSDexuan Cui 			0x75, 0x21, 0xad, 0x3f, 0x01, 0xfe)
12940f98829aSDexuan Cui 
12950f98829aSDexuan Cui /*
129646a97191SGreg Kroah-Hartman  * Common header for Hyper-V ICs
129746a97191SGreg Kroah-Hartman  */
129846a97191SGreg Kroah-Hartman 
129946a97191SGreg Kroah-Hartman #define ICMSGTYPE_NEGOTIATE		0
130046a97191SGreg Kroah-Hartman #define ICMSGTYPE_HEARTBEAT		1
130146a97191SGreg Kroah-Hartman #define ICMSGTYPE_KVPEXCHANGE		2
130246a97191SGreg Kroah-Hartman #define ICMSGTYPE_SHUTDOWN		3
130346a97191SGreg Kroah-Hartman #define ICMSGTYPE_TIMESYNC		4
130446a97191SGreg Kroah-Hartman #define ICMSGTYPE_VSS			5
130546a97191SGreg Kroah-Hartman 
130646a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_TRANSACTION	1
130746a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_REQUEST		2
130846a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_RESPONSE		4
130946a97191SGreg Kroah-Hartman 
131046a97191SGreg Kroah-Hartman 
131146a97191SGreg Kroah-Hartman /*
131246a97191SGreg Kroah-Hartman  * While we want to handle util services as regular devices,
131346a97191SGreg Kroah-Hartman  * there is only one instance of each of these services; so
131446a97191SGreg Kroah-Hartman  * we statically allocate the service specific state.
131546a97191SGreg Kroah-Hartman  */
131646a97191SGreg Kroah-Hartman 
131746a97191SGreg Kroah-Hartman struct hv_util_service {
131846a97191SGreg Kroah-Hartman 	u8 *recv_buffer;
1319b9830d12SK. Y. Srinivasan 	void *channel;
132046a97191SGreg Kroah-Hartman 	void (*util_cb)(void *);
132146a97191SGreg Kroah-Hartman 	int (*util_init)(struct hv_util_service *);
132246a97191SGreg Kroah-Hartman 	void (*util_deinit)(void);
132346a97191SGreg Kroah-Hartman };
132446a97191SGreg Kroah-Hartman 
132546a97191SGreg Kroah-Hartman struct vmbuspipe_hdr {
132646a97191SGreg Kroah-Hartman 	u32 flags;
132746a97191SGreg Kroah-Hartman 	u32 msgsize;
132846a97191SGreg Kroah-Hartman } __packed;
132946a97191SGreg Kroah-Hartman 
133046a97191SGreg Kroah-Hartman struct ic_version {
133146a97191SGreg Kroah-Hartman 	u16 major;
133246a97191SGreg Kroah-Hartman 	u16 minor;
133346a97191SGreg Kroah-Hartman } __packed;
133446a97191SGreg Kroah-Hartman 
133546a97191SGreg Kroah-Hartman struct icmsg_hdr {
133646a97191SGreg Kroah-Hartman 	struct ic_version icverframe;
133746a97191SGreg Kroah-Hartman 	u16 icmsgtype;
133846a97191SGreg Kroah-Hartman 	struct ic_version icvermsg;
133946a97191SGreg Kroah-Hartman 	u16 icmsgsize;
134046a97191SGreg Kroah-Hartman 	u32 status;
134146a97191SGreg Kroah-Hartman 	u8 ictransaction_id;
134246a97191SGreg Kroah-Hartman 	u8 icflags;
134346a97191SGreg Kroah-Hartman 	u8 reserved[2];
134446a97191SGreg Kroah-Hartman } __packed;
134546a97191SGreg Kroah-Hartman 
134646a97191SGreg Kroah-Hartman struct icmsg_negotiate {
134746a97191SGreg Kroah-Hartman 	u16 icframe_vercnt;
134846a97191SGreg Kroah-Hartman 	u16 icmsg_vercnt;
134946a97191SGreg Kroah-Hartman 	u32 reserved;
135046a97191SGreg Kroah-Hartman 	struct ic_version icversion_data[1]; /* any size array */
135146a97191SGreg Kroah-Hartman } __packed;
135246a97191SGreg Kroah-Hartman 
135346a97191SGreg Kroah-Hartman struct shutdown_msg_data {
135446a97191SGreg Kroah-Hartman 	u32 reason_code;
135546a97191SGreg Kroah-Hartman 	u32 timeout_seconds;
135646a97191SGreg Kroah-Hartman 	u32 flags;
135746a97191SGreg Kroah-Hartman 	u8  display_message[2048];
135846a97191SGreg Kroah-Hartman } __packed;
135946a97191SGreg Kroah-Hartman 
136046a97191SGreg Kroah-Hartman struct heartbeat_msg_data {
136146a97191SGreg Kroah-Hartman 	u64 seq_num;
136246a97191SGreg Kroah-Hartman 	u32 reserved[8];
136346a97191SGreg Kroah-Hartman } __packed;
136446a97191SGreg Kroah-Hartman 
136546a97191SGreg Kroah-Hartman /* Time Sync IC defs */
136646a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_PROBE	0
136746a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_SYNC	1
136846a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_SAMPLE	2
136946a97191SGreg Kroah-Hartman 
137046a97191SGreg Kroah-Hartman #ifdef __x86_64__
137146a97191SGreg Kroah-Hartman #define WLTIMEDELTA	116444736000000000L	/* in 100ns unit */
137246a97191SGreg Kroah-Hartman #else
137346a97191SGreg Kroah-Hartman #define WLTIMEDELTA	116444736000000000LL
137446a97191SGreg Kroah-Hartman #endif
137546a97191SGreg Kroah-Hartman 
137646a97191SGreg Kroah-Hartman struct ictimesync_data {
137746a97191SGreg Kroah-Hartman 	u64 parenttime;
137846a97191SGreg Kroah-Hartman 	u64 childtime;
137946a97191SGreg Kroah-Hartman 	u64 roundtriptime;
138046a97191SGreg Kroah-Hartman 	u8 flags;
138146a97191SGreg Kroah-Hartman } __packed;
138246a97191SGreg Kroah-Hartman 
13838e1d2607SAlex Ng struct ictimesync_ref_data {
13848e1d2607SAlex Ng 	u64 parenttime;
13858e1d2607SAlex Ng 	u64 vmreferencetime;
13868e1d2607SAlex Ng 	u8 flags;
13878e1d2607SAlex Ng 	char leapflags;
13888e1d2607SAlex Ng 	char stratum;
13898e1d2607SAlex Ng 	u8 reserved[3];
13908e1d2607SAlex Ng } __packed;
13918e1d2607SAlex Ng 
139246a97191SGreg Kroah-Hartman struct hyperv_service_callback {
139346a97191SGreg Kroah-Hartman 	u8 msg_type;
139446a97191SGreg Kroah-Hartman 	char *log_msg;
139546a97191SGreg Kroah-Hartman 	uuid_le data;
139646a97191SGreg Kroah-Hartman 	struct vmbus_channel *channel;
139746a97191SGreg Kroah-Hartman 	void (*callback)(void *context);
139846a97191SGreg Kroah-Hartman };
139946a97191SGreg Kroah-Hartman 
1400c836d0abSK. Y. Srinivasan #define MAX_SRV_VER	0x7ffffff
1401a1656454SAlex Ng extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf,
1402a1656454SAlex Ng 				const int *fw_version, int fw_vercnt,
1403a1656454SAlex Ng 				const int *srv_version, int srv_vercnt,
1404a1656454SAlex Ng 				int *nego_fw_version, int *nego_srv_version);
140546a97191SGreg Kroah-Hartman 
1406192b2d78SK. Y. Srinivasan void hv_process_channel_removal(u32 relid);
140796dd86faSK. Y. Srinivasan 
14081f6ee4e7SK. Y. Srinivasan void vmbus_setevent(struct vmbus_channel *channel);
140937f7278bSK. Y. Srinivasan /*
141037f7278bSK. Y. Srinivasan  * Negotiated version with the Host.
141137f7278bSK. Y. Srinivasan  */
141237f7278bSK. Y. Srinivasan 
141337f7278bSK. Y. Srinivasan extern __u32 vmbus_proto_version;
141437f7278bSK. Y. Srinivasan 
14155c23a1a5SDexuan Cui int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
14165c23a1a5SDexuan Cui 				  const uuid_le *shv_host_servie_id);
14175cc47247SK. Y. Srinivasan void vmbus_set_event(struct vmbus_channel *channel);
1418687f32e6SK. Y. Srinivasan 
1419687f32e6SK. Y. Srinivasan /* Get the start of the ring buffer. */
1420687f32e6SK. Y. Srinivasan static inline void *
1421e4165a0fSStephen Hemminger hv_get_ring_buffer(const struct hv_ring_buffer_info *ring_info)
1422687f32e6SK. Y. Srinivasan {
1423e4165a0fSStephen Hemminger 	return ring_info->ring_buffer->buffer;
1424687f32e6SK. Y. Srinivasan }
1425687f32e6SK. Y. Srinivasan 
1426687f32e6SK. Y. Srinivasan /*
14276e47dd3eSStephen Hemminger  * Mask off host interrupt callback notifications
14286e47dd3eSStephen Hemminger  */
14296e47dd3eSStephen Hemminger static inline void hv_begin_read(struct hv_ring_buffer_info *rbi)
14306e47dd3eSStephen Hemminger {
14316e47dd3eSStephen Hemminger 	rbi->ring_buffer->interrupt_mask = 1;
14326e47dd3eSStephen Hemminger 
14336e47dd3eSStephen Hemminger 	/* make sure mask update is not reordered */
14346e47dd3eSStephen Hemminger 	virt_mb();
14356e47dd3eSStephen Hemminger }
14366e47dd3eSStephen Hemminger 
14376e47dd3eSStephen Hemminger /*
14386e47dd3eSStephen Hemminger  * Re-enable host callback and return number of outstanding bytes
14396e47dd3eSStephen Hemminger  */
14406e47dd3eSStephen Hemminger static inline u32 hv_end_read(struct hv_ring_buffer_info *rbi)
14416e47dd3eSStephen Hemminger {
14426e47dd3eSStephen Hemminger 
14436e47dd3eSStephen Hemminger 	rbi->ring_buffer->interrupt_mask = 0;
14446e47dd3eSStephen Hemminger 
14456e47dd3eSStephen Hemminger 	/* make sure mask update is not reordered */
14466e47dd3eSStephen Hemminger 	virt_mb();
14476e47dd3eSStephen Hemminger 
14486e47dd3eSStephen Hemminger 	/*
14496e47dd3eSStephen Hemminger 	 * Now check to see if the ring buffer is still empty.
14506e47dd3eSStephen Hemminger 	 * If it is not, we raced and we need to process new
14516e47dd3eSStephen Hemminger 	 * incoming messages.
14526e47dd3eSStephen Hemminger 	 */
14536e47dd3eSStephen Hemminger 	return hv_get_bytes_to_read(rbi);
14546e47dd3eSStephen Hemminger }
14556e47dd3eSStephen Hemminger 
14566e47dd3eSStephen Hemminger /*
1457ab028db4SK. Y. Srinivasan  * An API to support in-place processing of incoming VMBUS packets.
1458ab028db4SK. Y. Srinivasan  */
1459ab028db4SK. Y. Srinivasan 
1460f3dd3f47Sstephen hemminger /* Get data payload associated with descriptor */
1461f3dd3f47Sstephen hemminger static inline void *hv_pkt_data(const struct vmpacket_descriptor *desc)
1462f3dd3f47Sstephen hemminger {
1463f3dd3f47Sstephen hemminger 	return (void *)((unsigned long)desc + (desc->offset8 << 3));
1464f3dd3f47Sstephen hemminger }
1465f3dd3f47Sstephen hemminger 
1466f3dd3f47Sstephen hemminger /* Get data size associated with descriptor */
1467f3dd3f47Sstephen hemminger static inline u32 hv_pkt_datalen(const struct vmpacket_descriptor *desc)
1468f3dd3f47Sstephen hemminger {
1469f3dd3f47Sstephen hemminger 	return (desc->len8 << 3) - (desc->offset8 << 3);
1470f3dd3f47Sstephen hemminger }
1471f3dd3f47Sstephen hemminger 
1472f3dd3f47Sstephen hemminger 
1473f3dd3f47Sstephen hemminger struct vmpacket_descriptor *
1474f3dd3f47Sstephen hemminger hv_pkt_iter_first(struct vmbus_channel *channel);
1475f3dd3f47Sstephen hemminger 
1476f3dd3f47Sstephen hemminger struct vmpacket_descriptor *
1477f3dd3f47Sstephen hemminger __hv_pkt_iter_next(struct vmbus_channel *channel,
1478f3dd3f47Sstephen hemminger 		   const struct vmpacket_descriptor *pkt);
1479f3dd3f47Sstephen hemminger 
1480f3dd3f47Sstephen hemminger void hv_pkt_iter_close(struct vmbus_channel *channel);
1481f3dd3f47Sstephen hemminger 
1482f3dd3f47Sstephen hemminger /*
1483f3dd3f47Sstephen hemminger  * Get next packet descriptor from iterator
1484f3dd3f47Sstephen hemminger  * If at end of list, return NULL and update host.
1485f3dd3f47Sstephen hemminger  */
1486ab028db4SK. Y. Srinivasan static inline struct vmpacket_descriptor *
1487f3dd3f47Sstephen hemminger hv_pkt_iter_next(struct vmbus_channel *channel,
1488f3dd3f47Sstephen hemminger 		 const struct vmpacket_descriptor *pkt)
1489ab028db4SK. Y. Srinivasan {
1490f3dd3f47Sstephen hemminger 	struct vmpacket_descriptor *nxt;
1491ab028db4SK. Y. Srinivasan 
1492f3dd3f47Sstephen hemminger 	nxt = __hv_pkt_iter_next(channel, pkt);
1493f3dd3f47Sstephen hemminger 	if (!nxt)
1494f3dd3f47Sstephen hemminger 		hv_pkt_iter_close(channel);
1495ab028db4SK. Y. Srinivasan 
1496f3dd3f47Sstephen hemminger 	return nxt;
1497ab028db4SK. Y. Srinivasan }
1498ab028db4SK. Y. Srinivasan 
1499f3dd3f47Sstephen hemminger #define foreach_vmbus_pkt(pkt, channel) \
1500f3dd3f47Sstephen hemminger 	for (pkt = hv_pkt_iter_first(channel); pkt; \
1501f3dd3f47Sstephen hemminger 	    pkt = hv_pkt_iter_next(channel, pkt))
1502ab028db4SK. Y. Srinivasan 
150346a97191SGreg Kroah-Hartman #endif /* _HYPERV_H */
1504