xref: /linux-6.15/include/linux/hyperv.h (revision 3724287c)
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>
29c75efa97SAndrey Smetanin #include <uapi/asm/hyperv.h>
305267cf02SBjarke Istrup Pedersen 
312939437cSK. Y. Srinivasan #include <linux/types.h>
3246a97191SGreg Kroah-Hartman #include <linux/scatterlist.h>
3346a97191SGreg Kroah-Hartman #include <linux/list.h>
3446a97191SGreg Kroah-Hartman #include <linux/timer.h>
3546a97191SGreg Kroah-Hartman #include <linux/workqueue.h>
3646a97191SGreg Kroah-Hartman #include <linux/completion.h>
3746a97191SGreg Kroah-Hartman #include <linux/device.h>
3846a97191SGreg Kroah-Hartman #include <linux/mod_devicetable.h>
3946a97191SGreg Kroah-Hartman 
4046a97191SGreg Kroah-Hartman 
417e5ec368SK. Y. Srinivasan #define MAX_PAGE_BUFFER_COUNT				32
4246a97191SGreg Kroah-Hartman #define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
4346a97191SGreg Kroah-Hartman 
4446a97191SGreg Kroah-Hartman #pragma pack(push, 1)
4546a97191SGreg Kroah-Hartman 
4646a97191SGreg Kroah-Hartman /* Single-page buffer */
4746a97191SGreg Kroah-Hartman struct hv_page_buffer {
4846a97191SGreg Kroah-Hartman 	u32 len;
4946a97191SGreg Kroah-Hartman 	u32 offset;
5046a97191SGreg Kroah-Hartman 	u64 pfn;
5146a97191SGreg Kroah-Hartman };
5246a97191SGreg Kroah-Hartman 
5346a97191SGreg Kroah-Hartman /* Multiple-page buffer */
5446a97191SGreg Kroah-Hartman struct hv_multipage_buffer {
5546a97191SGreg Kroah-Hartman 	/* Length and Offset determines the # of pfns in the array */
5646a97191SGreg Kroah-Hartman 	u32 len;
5746a97191SGreg Kroah-Hartman 	u32 offset;
5846a97191SGreg Kroah-Hartman 	u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT];
5946a97191SGreg Kroah-Hartman };
6046a97191SGreg Kroah-Hartman 
61d61031eeSK. Y. Srinivasan /*
62d61031eeSK. Y. Srinivasan  * Multiple-page buffer array; the pfn array is variable size:
63d61031eeSK. Y. Srinivasan  * The number of entries in the PFN array is determined by
64d61031eeSK. Y. Srinivasan  * "len" and "offset".
65d61031eeSK. Y. Srinivasan  */
66d61031eeSK. Y. Srinivasan struct hv_mpb_array {
67d61031eeSK. Y. Srinivasan 	/* Length and Offset determines the # of pfns in the array */
68d61031eeSK. Y. Srinivasan 	u32 len;
69d61031eeSK. Y. Srinivasan 	u32 offset;
70d61031eeSK. Y. Srinivasan 	u64 pfn_array[];
71d61031eeSK. Y. Srinivasan };
72d61031eeSK. Y. Srinivasan 
7346a97191SGreg Kroah-Hartman /* 0x18 includes the proprietary packet header */
7446a97191SGreg Kroah-Hartman #define MAX_PAGE_BUFFER_PACKET		(0x18 +			\
7546a97191SGreg Kroah-Hartman 					(sizeof(struct hv_page_buffer) * \
7646a97191SGreg Kroah-Hartman 					 MAX_PAGE_BUFFER_COUNT))
7746a97191SGreg Kroah-Hartman #define MAX_MULTIPAGE_BUFFER_PACKET	(0x18 +			\
7846a97191SGreg Kroah-Hartman 					 sizeof(struct hv_multipage_buffer))
7946a97191SGreg Kroah-Hartman 
8046a97191SGreg Kroah-Hartman 
8146a97191SGreg Kroah-Hartman #pragma pack(pop)
8246a97191SGreg Kroah-Hartman 
8346a97191SGreg Kroah-Hartman struct hv_ring_buffer {
8446a97191SGreg Kroah-Hartman 	/* Offset in bytes from the start of ring data below */
8546a97191SGreg Kroah-Hartman 	u32 write_index;
8646a97191SGreg Kroah-Hartman 
8746a97191SGreg Kroah-Hartman 	/* Offset in bytes from the start of ring data below */
8846a97191SGreg Kroah-Hartman 	u32 read_index;
8946a97191SGreg Kroah-Hartman 
9046a97191SGreg Kroah-Hartman 	u32 interrupt_mask;
9146a97191SGreg Kroah-Hartman 
922416603eSK. Y. Srinivasan 	/*
932416603eSK. Y. Srinivasan 	 * Win8 uses some of the reserved bits to implement
942416603eSK. Y. Srinivasan 	 * interrupt driven flow management. On the send side
952416603eSK. Y. Srinivasan 	 * we can request that the receiver interrupt the sender
962416603eSK. Y. Srinivasan 	 * when the ring transitions from being full to being able
972416603eSK. Y. Srinivasan 	 * to handle a message of size "pending_send_sz".
982416603eSK. Y. Srinivasan 	 *
992416603eSK. Y. Srinivasan 	 * Add necessary state for this enhancement.
10046a97191SGreg Kroah-Hartman 	 */
1012416603eSK. Y. Srinivasan 	u32 pending_send_sz;
1022416603eSK. Y. Srinivasan 
1032416603eSK. Y. Srinivasan 	u32 reserved1[12];
1042416603eSK. Y. Srinivasan 
1052416603eSK. Y. Srinivasan 	union {
1062416603eSK. Y. Srinivasan 		struct {
1072416603eSK. Y. Srinivasan 			u32 feat_pending_send_sz:1;
1082416603eSK. Y. Srinivasan 		};
1092416603eSK. Y. Srinivasan 		u32 value;
1102416603eSK. Y. Srinivasan 	} feature_bits;
1112416603eSK. Y. Srinivasan 
1122416603eSK. Y. Srinivasan 	/* Pad it to PAGE_SIZE so that data starts on page boundary */
1132416603eSK. Y. Srinivasan 	u8	reserved2[4028];
11446a97191SGreg Kroah-Hartman 
11546a97191SGreg Kroah-Hartman 	/*
11646a97191SGreg Kroah-Hartman 	 * Ring data starts here + RingDataStartOffset
11746a97191SGreg Kroah-Hartman 	 * !!! DO NOT place any fields below this !!!
11846a97191SGreg Kroah-Hartman 	 */
11946a97191SGreg Kroah-Hartman 	u8 buffer[0];
12046a97191SGreg Kroah-Hartman } __packed;
12146a97191SGreg Kroah-Hartman 
12246a97191SGreg Kroah-Hartman struct hv_ring_buffer_info {
12346a97191SGreg Kroah-Hartman 	struct hv_ring_buffer *ring_buffer;
12446a97191SGreg Kroah-Hartman 	u32 ring_size;			/* Include the shared header */
12546a97191SGreg Kroah-Hartman 	spinlock_t ring_lock;
12646a97191SGreg Kroah-Hartman 
12746a97191SGreg Kroah-Hartman 	u32 ring_datasize;		/* < ring_size */
12846a97191SGreg Kroah-Hartman 	u32 ring_data_startoffset;
129ab028db4SK. Y. Srinivasan 	u32 priv_write_index;
130ab028db4SK. Y. Srinivasan 	u32 priv_read_index;
13146a97191SGreg Kroah-Hartman };
13246a97191SGreg Kroah-Hartman 
13333be96e4SHaiyang Zhang /*
13433be96e4SHaiyang Zhang  *
13533be96e4SHaiyang Zhang  * hv_get_ringbuffer_availbytes()
13633be96e4SHaiyang Zhang  *
13733be96e4SHaiyang Zhang  * Get number of bytes available to read and to write to
13833be96e4SHaiyang Zhang  * for the specified ring buffer
13933be96e4SHaiyang Zhang  */
14033be96e4SHaiyang Zhang static inline void
14133be96e4SHaiyang Zhang hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
14233be96e4SHaiyang Zhang 			  u32 *read, u32 *write)
14333be96e4SHaiyang Zhang {
14433be96e4SHaiyang Zhang 	u32 read_loc, write_loc, dsize;
14533be96e4SHaiyang Zhang 
14633be96e4SHaiyang Zhang 	/* Capture the read/write indices before they changed */
14733be96e4SHaiyang Zhang 	read_loc = rbi->ring_buffer->read_index;
14833be96e4SHaiyang Zhang 	write_loc = rbi->ring_buffer->write_index;
14933be96e4SHaiyang Zhang 	dsize = rbi->ring_datasize;
15033be96e4SHaiyang Zhang 
15133be96e4SHaiyang Zhang 	*write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
15233be96e4SHaiyang Zhang 		read_loc - write_loc;
15333be96e4SHaiyang Zhang 	*read = dsize - *write;
15433be96e4SHaiyang Zhang }
15533be96e4SHaiyang Zhang 
156a6341f00SK. Y. Srinivasan static inline u32 hv_get_bytes_to_read(struct hv_ring_buffer_info *rbi)
157a6341f00SK. Y. Srinivasan {
158a6341f00SK. Y. Srinivasan 	u32 read_loc, write_loc, dsize, read;
159a6341f00SK. Y. Srinivasan 
160a6341f00SK. Y. Srinivasan 	dsize = rbi->ring_datasize;
161a6341f00SK. Y. Srinivasan 	read_loc = rbi->ring_buffer->read_index;
162a6341f00SK. Y. Srinivasan 	write_loc = READ_ONCE(rbi->ring_buffer->write_index);
163a6341f00SK. Y. Srinivasan 
164a6341f00SK. Y. Srinivasan 	read = write_loc >= read_loc ? (write_loc - read_loc) :
165a6341f00SK. Y. Srinivasan 		(dsize - read_loc) + write_loc;
166a6341f00SK. Y. Srinivasan 
167a6341f00SK. Y. Srinivasan 	return read;
168a6341f00SK. Y. Srinivasan }
169a6341f00SK. Y. Srinivasan 
170a6341f00SK. Y. Srinivasan static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
171a6341f00SK. Y. Srinivasan {
172a6341f00SK. Y. Srinivasan 	u32 read_loc, write_loc, dsize, write;
173a6341f00SK. Y. Srinivasan 
174a6341f00SK. Y. Srinivasan 	dsize = rbi->ring_datasize;
175a6341f00SK. Y. Srinivasan 	read_loc = READ_ONCE(rbi->ring_buffer->read_index);
176a6341f00SK. Y. Srinivasan 	write_loc = rbi->ring_buffer->write_index;
177a6341f00SK. Y. Srinivasan 
178a6341f00SK. Y. Srinivasan 	write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
179a6341f00SK. Y. Srinivasan 		read_loc - write_loc;
180a6341f00SK. Y. Srinivasan 	return write;
181a6341f00SK. Y. Srinivasan }
182a6341f00SK. Y. Srinivasan 
183eafa7072SK. Y. Srinivasan /*
184eafa7072SK. Y. Srinivasan  * VMBUS version is 32 bit entity broken up into
185eafa7072SK. Y. Srinivasan  * two 16 bit quantities: major_number. minor_number.
186eafa7072SK. Y. Srinivasan  *
187eafa7072SK. Y. Srinivasan  * 0 . 13 (Windows Server 2008)
188eafa7072SK. Y. Srinivasan  * 1 . 1  (Windows 7)
189eafa7072SK. Y. Srinivasan  * 2 . 4  (Windows 8)
19003367ef5SK. Y. Srinivasan  * 3 . 0  (Windows 8 R2)
1916c4e5f9cSKeith Mange  * 4 . 0  (Windows 10)
192eafa7072SK. Y. Srinivasan  */
193eafa7072SK. Y. Srinivasan 
194eafa7072SK. Y. Srinivasan #define VERSION_WS2008  ((0 << 16) | (13))
195eafa7072SK. Y. Srinivasan #define VERSION_WIN7    ((1 << 16) | (1))
196eafa7072SK. Y. Srinivasan #define VERSION_WIN8    ((2 << 16) | (4))
19703367ef5SK. Y. Srinivasan #define VERSION_WIN8_1    ((3 << 16) | (0))
1986c4e5f9cSKeith Mange #define VERSION_WIN10	((4 << 16) | (0))
199eafa7072SK. Y. Srinivasan 
200eafa7072SK. Y. Srinivasan #define VERSION_INVAL -1
201eafa7072SK. Y. Srinivasan 
2026c4e5f9cSKeith Mange #define VERSION_CURRENT VERSION_WIN10
20346a97191SGreg Kroah-Hartman 
20446a97191SGreg Kroah-Hartman /* Make maximum size of pipe payload of 16K */
20546a97191SGreg Kroah-Hartman #define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
20646a97191SGreg Kroah-Hartman 
20746a97191SGreg Kroah-Hartman /* Define PipeMode values. */
20846a97191SGreg Kroah-Hartman #define VMBUS_PIPE_TYPE_BYTE		0x00000000
20946a97191SGreg Kroah-Hartman #define VMBUS_PIPE_TYPE_MESSAGE		0x00000004
21046a97191SGreg Kroah-Hartman 
21146a97191SGreg Kroah-Hartman /* The size of the user defined data buffer for non-pipe offers. */
21246a97191SGreg Kroah-Hartman #define MAX_USER_DEFINED_BYTES		120
21346a97191SGreg Kroah-Hartman 
21446a97191SGreg Kroah-Hartman /* The size of the user defined data buffer for pipe offers. */
21546a97191SGreg Kroah-Hartman #define MAX_PIPE_USER_DEFINED_BYTES	116
21646a97191SGreg Kroah-Hartman 
21746a97191SGreg Kroah-Hartman /*
21846a97191SGreg Kroah-Hartman  * At the center of the Channel Management library is the Channel Offer. This
21946a97191SGreg Kroah-Hartman  * struct contains the fundamental information about an offer.
22046a97191SGreg Kroah-Hartman  */
22146a97191SGreg Kroah-Hartman struct vmbus_channel_offer {
22246a97191SGreg Kroah-Hartman 	uuid_le if_type;
22346a97191SGreg Kroah-Hartman 	uuid_le if_instance;
22429423b7eSK. Y. Srinivasan 
22529423b7eSK. Y. Srinivasan 	/*
22629423b7eSK. Y. Srinivasan 	 * These two fields are not currently used.
22729423b7eSK. Y. Srinivasan 	 */
22829423b7eSK. Y. Srinivasan 	u64 reserved1;
22929423b7eSK. Y. Srinivasan 	u64 reserved2;
23029423b7eSK. Y. Srinivasan 
23146a97191SGreg Kroah-Hartman 	u16 chn_flags;
23246a97191SGreg Kroah-Hartman 	u16 mmio_megabytes;		/* in bytes * 1024 * 1024 */
23346a97191SGreg Kroah-Hartman 
23446a97191SGreg Kroah-Hartman 	union {
23546a97191SGreg Kroah-Hartman 		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
23646a97191SGreg Kroah-Hartman 		struct {
23746a97191SGreg Kroah-Hartman 			unsigned char user_def[MAX_USER_DEFINED_BYTES];
23846a97191SGreg Kroah-Hartman 		} std;
23946a97191SGreg Kroah-Hartman 
24046a97191SGreg Kroah-Hartman 		/*
24146a97191SGreg Kroah-Hartman 		 * Pipes:
24246a97191SGreg Kroah-Hartman 		 * The following sructure is an integrated pipe protocol, which
24346a97191SGreg Kroah-Hartman 		 * is implemented on top of standard user-defined data. Pipe
24446a97191SGreg Kroah-Hartman 		 * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own
24546a97191SGreg Kroah-Hartman 		 * use.
24646a97191SGreg Kroah-Hartman 		 */
24746a97191SGreg Kroah-Hartman 		struct {
24846a97191SGreg Kroah-Hartman 			u32  pipe_mode;
24946a97191SGreg Kroah-Hartman 			unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES];
25046a97191SGreg Kroah-Hartman 		} pipe;
25146a97191SGreg Kroah-Hartman 	} u;
25229423b7eSK. Y. Srinivasan 	/*
25329423b7eSK. Y. Srinivasan 	 * The sub_channel_index is defined in win8.
25429423b7eSK. Y. Srinivasan 	 */
25529423b7eSK. Y. Srinivasan 	u16 sub_channel_index;
25629423b7eSK. Y. Srinivasan 	u16 reserved3;
25746a97191SGreg Kroah-Hartman } __packed;
25846a97191SGreg Kroah-Hartman 
25946a97191SGreg Kroah-Hartman /* Server Flags */
26046a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
26146a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES	2
26246a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS		4
26346a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_NAMED_PIPE_MODE			0x10
26446a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_LOOPBACK_OFFER			0x100
26546a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_PARENT_OFFER			0x200
26646a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION	0x400
267e8d6ca02SDexuan Cui #define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER		0x2000
26846a97191SGreg Kroah-Hartman 
26946a97191SGreg Kroah-Hartman struct vmpacket_descriptor {
27046a97191SGreg Kroah-Hartman 	u16 type;
27146a97191SGreg Kroah-Hartman 	u16 offset8;
27246a97191SGreg Kroah-Hartman 	u16 len8;
27346a97191SGreg Kroah-Hartman 	u16 flags;
27446a97191SGreg Kroah-Hartman 	u64 trans_id;
27546a97191SGreg Kroah-Hartman } __packed;
27646a97191SGreg Kroah-Hartman 
27746a97191SGreg Kroah-Hartman struct vmpacket_header {
27846a97191SGreg Kroah-Hartman 	u32 prev_pkt_start_offset;
27946a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor descriptor;
28046a97191SGreg Kroah-Hartman } __packed;
28146a97191SGreg Kroah-Hartman 
28246a97191SGreg Kroah-Hartman struct vmtransfer_page_range {
28346a97191SGreg Kroah-Hartman 	u32 byte_count;
28446a97191SGreg Kroah-Hartman 	u32 byte_offset;
28546a97191SGreg Kroah-Hartman } __packed;
28646a97191SGreg Kroah-Hartman 
28746a97191SGreg Kroah-Hartman struct vmtransfer_page_packet_header {
28846a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
28946a97191SGreg Kroah-Hartman 	u16 xfer_pageset_id;
2901508d811SK. Y. Srinivasan 	u8  sender_owns_set;
29146a97191SGreg Kroah-Hartman 	u8 reserved;
29246a97191SGreg Kroah-Hartman 	u32 range_cnt;
29346a97191SGreg Kroah-Hartman 	struct vmtransfer_page_range ranges[1];
29446a97191SGreg Kroah-Hartman } __packed;
29546a97191SGreg Kroah-Hartman 
29646a97191SGreg Kroah-Hartman struct vmgpadl_packet_header {
29746a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
29846a97191SGreg Kroah-Hartman 	u32 gpadl;
29946a97191SGreg Kroah-Hartman 	u32 reserved;
30046a97191SGreg Kroah-Hartman } __packed;
30146a97191SGreg Kroah-Hartman 
30246a97191SGreg Kroah-Hartman struct vmadd_remove_transfer_page_set {
30346a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
30446a97191SGreg Kroah-Hartman 	u32 gpadl;
30546a97191SGreg Kroah-Hartman 	u16 xfer_pageset_id;
30646a97191SGreg Kroah-Hartman 	u16 reserved;
30746a97191SGreg Kroah-Hartman } __packed;
30846a97191SGreg Kroah-Hartman 
30946a97191SGreg Kroah-Hartman /*
31046a97191SGreg Kroah-Hartman  * This structure defines a range in guest physical space that can be made to
31146a97191SGreg Kroah-Hartman  * look virtually contiguous.
31246a97191SGreg Kroah-Hartman  */
31346a97191SGreg Kroah-Hartman struct gpa_range {
31446a97191SGreg Kroah-Hartman 	u32 byte_count;
31546a97191SGreg Kroah-Hartman 	u32 byte_offset;
31646a97191SGreg Kroah-Hartman 	u64 pfn_array[0];
31746a97191SGreg Kroah-Hartman };
31846a97191SGreg Kroah-Hartman 
31946a97191SGreg Kroah-Hartman /*
32046a97191SGreg Kroah-Hartman  * This is the format for an Establish Gpadl packet, which contains a handle by
32146a97191SGreg Kroah-Hartman  * which this GPADL will be known and a set of GPA ranges associated with it.
32246a97191SGreg Kroah-Hartman  * This can be converted to a MDL by the guest OS.  If there are multiple GPA
32346a97191SGreg Kroah-Hartman  * ranges, then the resulting MDL will be "chained," representing multiple VA
32446a97191SGreg Kroah-Hartman  * ranges.
32546a97191SGreg Kroah-Hartman  */
32646a97191SGreg Kroah-Hartman struct vmestablish_gpadl {
32746a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
32846a97191SGreg Kroah-Hartman 	u32 gpadl;
32946a97191SGreg Kroah-Hartman 	u32 range_cnt;
33046a97191SGreg Kroah-Hartman 	struct gpa_range range[1];
33146a97191SGreg Kroah-Hartman } __packed;
33246a97191SGreg Kroah-Hartman 
33346a97191SGreg Kroah-Hartman /*
33446a97191SGreg Kroah-Hartman  * This is the format for a Teardown Gpadl packet, which indicates that the
33546a97191SGreg Kroah-Hartman  * GPADL handle in the Establish Gpadl packet will never be referenced again.
33646a97191SGreg Kroah-Hartman  */
33746a97191SGreg Kroah-Hartman struct vmteardown_gpadl {
33846a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
33946a97191SGreg Kroah-Hartman 	u32 gpadl;
34046a97191SGreg Kroah-Hartman 	u32 reserved;	/* for alignment to a 8-byte boundary */
34146a97191SGreg Kroah-Hartman } __packed;
34246a97191SGreg Kroah-Hartman 
34346a97191SGreg Kroah-Hartman /*
34446a97191SGreg Kroah-Hartman  * This is the format for a GPA-Direct packet, which contains a set of GPA
34546a97191SGreg Kroah-Hartman  * ranges, in addition to commands and/or data.
34646a97191SGreg Kroah-Hartman  */
34746a97191SGreg Kroah-Hartman struct vmdata_gpa_direct {
34846a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
34946a97191SGreg Kroah-Hartman 	u32 reserved;
35046a97191SGreg Kroah-Hartman 	u32 range_cnt;
35146a97191SGreg Kroah-Hartman 	struct gpa_range range[1];
35246a97191SGreg Kroah-Hartman } __packed;
35346a97191SGreg Kroah-Hartman 
35446a97191SGreg Kroah-Hartman /* This is the format for a Additional Data Packet. */
35546a97191SGreg Kroah-Hartman struct vmadditional_data {
35646a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
35746a97191SGreg Kroah-Hartman 	u64 total_bytes;
35846a97191SGreg Kroah-Hartman 	u32 offset;
35946a97191SGreg Kroah-Hartman 	u32 byte_cnt;
36046a97191SGreg Kroah-Hartman 	unsigned char data[1];
36146a97191SGreg Kroah-Hartman } __packed;
36246a97191SGreg Kroah-Hartman 
36346a97191SGreg Kroah-Hartman union vmpacket_largest_possible_header {
36446a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor simple_hdr;
36546a97191SGreg Kroah-Hartman 	struct vmtransfer_page_packet_header xfer_page_hdr;
36646a97191SGreg Kroah-Hartman 	struct vmgpadl_packet_header gpadl_hdr;
36746a97191SGreg Kroah-Hartman 	struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr;
36846a97191SGreg Kroah-Hartman 	struct vmestablish_gpadl establish_gpadl_hdr;
36946a97191SGreg Kroah-Hartman 	struct vmteardown_gpadl teardown_gpadl_hdr;
37046a97191SGreg Kroah-Hartman 	struct vmdata_gpa_direct data_gpa_direct_hdr;
37146a97191SGreg Kroah-Hartman };
37246a97191SGreg Kroah-Hartman 
37346a97191SGreg Kroah-Hartman #define VMPACKET_DATA_START_ADDRESS(__packet)	\
37446a97191SGreg Kroah-Hartman 	(void *)(((unsigned char *)__packet) +	\
37546a97191SGreg Kroah-Hartman 	 ((struct vmpacket_descriptor)__packet)->offset8 * 8)
37646a97191SGreg Kroah-Hartman 
37746a97191SGreg Kroah-Hartman #define VMPACKET_DATA_LENGTH(__packet)		\
37846a97191SGreg Kroah-Hartman 	((((struct vmpacket_descriptor)__packet)->len8 -	\
37946a97191SGreg Kroah-Hartman 	  ((struct vmpacket_descriptor)__packet)->offset8) * 8)
38046a97191SGreg Kroah-Hartman 
38146a97191SGreg Kroah-Hartman #define VMPACKET_TRANSFER_MODE(__packet)	\
38246a97191SGreg Kroah-Hartman 	(((struct IMPACT)__packet)->type)
38346a97191SGreg Kroah-Hartman 
38446a97191SGreg Kroah-Hartman enum vmbus_packet_type {
38546a97191SGreg Kroah-Hartman 	VM_PKT_INVALID				= 0x0,
38646a97191SGreg Kroah-Hartman 	VM_PKT_SYNCH				= 0x1,
38746a97191SGreg Kroah-Hartman 	VM_PKT_ADD_XFER_PAGESET			= 0x2,
38846a97191SGreg Kroah-Hartman 	VM_PKT_RM_XFER_PAGESET			= 0x3,
38946a97191SGreg Kroah-Hartman 	VM_PKT_ESTABLISH_GPADL			= 0x4,
39046a97191SGreg Kroah-Hartman 	VM_PKT_TEARDOWN_GPADL			= 0x5,
39146a97191SGreg Kroah-Hartman 	VM_PKT_DATA_INBAND			= 0x6,
39246a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_XFER_PAGES		= 0x7,
39346a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_GPADL			= 0x8,
39446a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_GPA_DIRECT		= 0x9,
39546a97191SGreg Kroah-Hartman 	VM_PKT_CANCEL_REQUEST			= 0xa,
39646a97191SGreg Kroah-Hartman 	VM_PKT_COMP				= 0xb,
39746a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_ADDITIONAL_PKT	= 0xc,
39846a97191SGreg Kroah-Hartman 	VM_PKT_ADDITIONAL_DATA			= 0xd
39946a97191SGreg Kroah-Hartman };
40046a97191SGreg Kroah-Hartman 
40146a97191SGreg Kroah-Hartman #define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
40246a97191SGreg Kroah-Hartman 
40346a97191SGreg Kroah-Hartman 
40446a97191SGreg Kroah-Hartman /* Version 1 messages */
40546a97191SGreg Kroah-Hartman enum vmbus_channel_message_type {
40646a97191SGreg Kroah-Hartman 	CHANNELMSG_INVALID			=  0,
40746a97191SGreg Kroah-Hartman 	CHANNELMSG_OFFERCHANNEL		=  1,
40846a97191SGreg Kroah-Hartman 	CHANNELMSG_RESCIND_CHANNELOFFER	=  2,
40946a97191SGreg Kroah-Hartman 	CHANNELMSG_REQUESTOFFERS		=  3,
41046a97191SGreg Kroah-Hartman 	CHANNELMSG_ALLOFFERS_DELIVERED	=  4,
41146a97191SGreg Kroah-Hartman 	CHANNELMSG_OPENCHANNEL		=  5,
41246a97191SGreg Kroah-Hartman 	CHANNELMSG_OPENCHANNEL_RESULT		=  6,
41346a97191SGreg Kroah-Hartman 	CHANNELMSG_CLOSECHANNEL		=  7,
41446a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_HEADER		=  8,
41546a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_BODY			=  9,
41646a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_CREATED		= 10,
41746a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_TEARDOWN		= 11,
41846a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_TORNDOWN		= 12,
41946a97191SGreg Kroah-Hartman 	CHANNELMSG_RELID_RELEASED		= 13,
42046a97191SGreg Kroah-Hartman 	CHANNELMSG_INITIATE_CONTACT		= 14,
42146a97191SGreg Kroah-Hartman 	CHANNELMSG_VERSION_RESPONSE		= 15,
42246a97191SGreg Kroah-Hartman 	CHANNELMSG_UNLOAD			= 16,
4232db84effSK. Y. Srinivasan 	CHANNELMSG_UNLOAD_RESPONSE		= 17,
4245c23a1a5SDexuan Cui 	CHANNELMSG_18				= 18,
4255c23a1a5SDexuan Cui 	CHANNELMSG_19				= 19,
4265c23a1a5SDexuan Cui 	CHANNELMSG_20				= 20,
4275c23a1a5SDexuan Cui 	CHANNELMSG_TL_CONNECT_REQUEST		= 21,
42846a97191SGreg Kroah-Hartman 	CHANNELMSG_COUNT
42946a97191SGreg Kroah-Hartman };
43046a97191SGreg Kroah-Hartman 
43146a97191SGreg Kroah-Hartman struct vmbus_channel_message_header {
43246a97191SGreg Kroah-Hartman 	enum vmbus_channel_message_type msgtype;
43346a97191SGreg Kroah-Hartman 	u32 padding;
43446a97191SGreg Kroah-Hartman } __packed;
43546a97191SGreg Kroah-Hartman 
43646a97191SGreg Kroah-Hartman /* Query VMBus Version parameters */
43746a97191SGreg Kroah-Hartman struct vmbus_channel_query_vmbus_version {
43846a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
43946a97191SGreg Kroah-Hartman 	u32 version;
44046a97191SGreg Kroah-Hartman } __packed;
44146a97191SGreg Kroah-Hartman 
44246a97191SGreg Kroah-Hartman /* VMBus Version Supported parameters */
44346a97191SGreg Kroah-Hartman struct vmbus_channel_version_supported {
44446a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
4451508d811SK. Y. Srinivasan 	u8 version_supported;
44646a97191SGreg Kroah-Hartman } __packed;
44746a97191SGreg Kroah-Hartman 
44846a97191SGreg Kroah-Hartman /* Offer Channel parameters */
44946a97191SGreg Kroah-Hartman struct vmbus_channel_offer_channel {
45046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
45146a97191SGreg Kroah-Hartman 	struct vmbus_channel_offer offer;
45246a97191SGreg Kroah-Hartman 	u32 child_relid;
45346a97191SGreg Kroah-Hartman 	u8 monitorid;
45429423b7eSK. Y. Srinivasan 	/*
45529423b7eSK. Y. Srinivasan 	 * win7 and beyond splits this field into a bit field.
45629423b7eSK. Y. Srinivasan 	 */
45729423b7eSK. Y. Srinivasan 	u8 monitor_allocated:1;
45829423b7eSK. Y. Srinivasan 	u8 reserved:7;
45929423b7eSK. Y. Srinivasan 	/*
46029423b7eSK. Y. Srinivasan 	 * These are new fields added in win7 and later.
46129423b7eSK. Y. Srinivasan 	 * Do not access these fields without checking the
46229423b7eSK. Y. Srinivasan 	 * negotiated protocol.
46329423b7eSK. Y. Srinivasan 	 *
46429423b7eSK. Y. Srinivasan 	 * If "is_dedicated_interrupt" is set, we must not set the
46529423b7eSK. Y. Srinivasan 	 * associated bit in the channel bitmap while sending the
46629423b7eSK. Y. Srinivasan 	 * interrupt to the host.
46729423b7eSK. Y. Srinivasan 	 *
46829423b7eSK. Y. Srinivasan 	 * connection_id is to be used in signaling the host.
46929423b7eSK. Y. Srinivasan 	 */
47029423b7eSK. Y. Srinivasan 	u16 is_dedicated_interrupt:1;
47129423b7eSK. Y. Srinivasan 	u16 reserved1:15;
47229423b7eSK. Y. Srinivasan 	u32 connection_id;
47346a97191SGreg Kroah-Hartman } __packed;
47446a97191SGreg Kroah-Hartman 
47546a97191SGreg Kroah-Hartman /* Rescind Offer parameters */
47646a97191SGreg Kroah-Hartman struct vmbus_channel_rescind_offer {
47746a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
47846a97191SGreg Kroah-Hartman 	u32 child_relid;
47946a97191SGreg Kroah-Hartman } __packed;
48046a97191SGreg Kroah-Hartman 
48146a97191SGreg Kroah-Hartman /*
48246a97191SGreg Kroah-Hartman  * Request Offer -- no parameters, SynIC message contains the partition ID
48346a97191SGreg Kroah-Hartman  * Set Snoop -- no parameters, SynIC message contains the partition ID
48446a97191SGreg Kroah-Hartman  * Clear Snoop -- no parameters, SynIC message contains the partition ID
48546a97191SGreg Kroah-Hartman  * All Offers Delivered -- no parameters, SynIC message contains the partition
48646a97191SGreg Kroah-Hartman  *		           ID
48746a97191SGreg Kroah-Hartman  * Flush Client -- no parameters, SynIC message contains the partition ID
48846a97191SGreg Kroah-Hartman  */
48946a97191SGreg Kroah-Hartman 
49046a97191SGreg Kroah-Hartman /* Open Channel parameters */
49146a97191SGreg Kroah-Hartman struct vmbus_channel_open_channel {
49246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
49346a97191SGreg Kroah-Hartman 
49446a97191SGreg Kroah-Hartman 	/* Identifies the specific VMBus channel that is being opened. */
49546a97191SGreg Kroah-Hartman 	u32 child_relid;
49646a97191SGreg Kroah-Hartman 
49746a97191SGreg Kroah-Hartman 	/* ID making a particular open request at a channel offer unique. */
49846a97191SGreg Kroah-Hartman 	u32 openid;
49946a97191SGreg Kroah-Hartman 
50046a97191SGreg Kroah-Hartman 	/* GPADL for the channel's ring buffer. */
50146a97191SGreg Kroah-Hartman 	u32 ringbuffer_gpadlhandle;
50246a97191SGreg Kroah-Hartman 
503abbf3b2aSK. Y. Srinivasan 	/*
504abbf3b2aSK. Y. Srinivasan 	 * Starting with win8, this field will be used to specify
505abbf3b2aSK. Y. Srinivasan 	 * the target virtual processor on which to deliver the interrupt for
506abbf3b2aSK. Y. Srinivasan 	 * the host to guest communication.
507abbf3b2aSK. Y. Srinivasan 	 * Prior to win8, incoming channel interrupts would only
508abbf3b2aSK. Y. Srinivasan 	 * be delivered on cpu 0. Setting this value to 0 would
509abbf3b2aSK. Y. Srinivasan 	 * preserve the earlier behavior.
510abbf3b2aSK. Y. Srinivasan 	 */
511abbf3b2aSK. Y. Srinivasan 	u32 target_vp;
51246a97191SGreg Kroah-Hartman 
51346a97191SGreg Kroah-Hartman 	/*
51446a97191SGreg Kroah-Hartman 	* The upstream ring buffer begins at offset zero in the memory
51546a97191SGreg Kroah-Hartman 	* described by RingBufferGpadlHandle. The downstream ring buffer
51646a97191SGreg Kroah-Hartman 	* follows it at this offset (in pages).
51746a97191SGreg Kroah-Hartman 	*/
51846a97191SGreg Kroah-Hartman 	u32 downstream_ringbuffer_pageoffset;
51946a97191SGreg Kroah-Hartman 
52046a97191SGreg Kroah-Hartman 	/* User-specific data to be passed along to the server endpoint. */
52146a97191SGreg Kroah-Hartman 	unsigned char userdata[MAX_USER_DEFINED_BYTES];
52246a97191SGreg Kroah-Hartman } __packed;
52346a97191SGreg Kroah-Hartman 
52446a97191SGreg Kroah-Hartman /* Open Channel Result parameters */
52546a97191SGreg Kroah-Hartman struct vmbus_channel_open_result {
52646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
52746a97191SGreg Kroah-Hartman 	u32 child_relid;
52846a97191SGreg Kroah-Hartman 	u32 openid;
52946a97191SGreg Kroah-Hartman 	u32 status;
53046a97191SGreg Kroah-Hartman } __packed;
53146a97191SGreg Kroah-Hartman 
53246a97191SGreg Kroah-Hartman /* Close channel parameters; */
53346a97191SGreg Kroah-Hartman struct vmbus_channel_close_channel {
53446a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
53546a97191SGreg Kroah-Hartman 	u32 child_relid;
53646a97191SGreg Kroah-Hartman } __packed;
53746a97191SGreg Kroah-Hartman 
53846a97191SGreg Kroah-Hartman /* Channel Message GPADL */
53946a97191SGreg Kroah-Hartman #define GPADL_TYPE_RING_BUFFER		1
54046a97191SGreg Kroah-Hartman #define GPADL_TYPE_SERVER_SAVE_AREA	2
54146a97191SGreg Kroah-Hartman #define GPADL_TYPE_TRANSACTION		8
54246a97191SGreg Kroah-Hartman 
54346a97191SGreg Kroah-Hartman /*
54446a97191SGreg Kroah-Hartman  * The number of PFNs in a GPADL message is defined by the number of
54546a97191SGreg Kroah-Hartman  * pages that would be spanned by ByteCount and ByteOffset.  If the
54646a97191SGreg Kroah-Hartman  * implied number of PFNs won't fit in this packet, there will be a
54746a97191SGreg Kroah-Hartman  * follow-up packet that contains more.
54846a97191SGreg Kroah-Hartman  */
54946a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_header {
55046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
55146a97191SGreg Kroah-Hartman 	u32 child_relid;
55246a97191SGreg Kroah-Hartman 	u32 gpadl;
55346a97191SGreg Kroah-Hartman 	u16 range_buflen;
55446a97191SGreg Kroah-Hartman 	u16 rangecount;
55546a97191SGreg Kroah-Hartman 	struct gpa_range range[0];
55646a97191SGreg Kroah-Hartman } __packed;
55746a97191SGreg Kroah-Hartman 
55846a97191SGreg Kroah-Hartman /* This is the followup packet that contains more PFNs. */
55946a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_body {
56046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
56146a97191SGreg Kroah-Hartman 	u32 msgnumber;
56246a97191SGreg Kroah-Hartman 	u32 gpadl;
56346a97191SGreg Kroah-Hartman 	u64 pfn[0];
56446a97191SGreg Kroah-Hartman } __packed;
56546a97191SGreg Kroah-Hartman 
56646a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_created {
56746a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
56846a97191SGreg Kroah-Hartman 	u32 child_relid;
56946a97191SGreg Kroah-Hartman 	u32 gpadl;
57046a97191SGreg Kroah-Hartman 	u32 creation_status;
57146a97191SGreg Kroah-Hartman } __packed;
57246a97191SGreg Kroah-Hartman 
57346a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_teardown {
57446a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
57546a97191SGreg Kroah-Hartman 	u32 child_relid;
57646a97191SGreg Kroah-Hartman 	u32 gpadl;
57746a97191SGreg Kroah-Hartman } __packed;
57846a97191SGreg Kroah-Hartman 
57946a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_torndown {
58046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
58146a97191SGreg Kroah-Hartman 	u32 gpadl;
58246a97191SGreg Kroah-Hartman } __packed;
58346a97191SGreg Kroah-Hartman 
58446a97191SGreg Kroah-Hartman struct vmbus_channel_relid_released {
58546a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
58646a97191SGreg Kroah-Hartman 	u32 child_relid;
58746a97191SGreg Kroah-Hartman } __packed;
58846a97191SGreg Kroah-Hartman 
58946a97191SGreg Kroah-Hartman struct vmbus_channel_initiate_contact {
59046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
59146a97191SGreg Kroah-Hartman 	u32 vmbus_version_requested;
592e28bab48SK. Y. Srinivasan 	u32 target_vcpu; /* The VCPU the host should respond to */
59346a97191SGreg Kroah-Hartman 	u64 interrupt_page;
59446a97191SGreg Kroah-Hartman 	u64 monitor_page1;
59546a97191SGreg Kroah-Hartman 	u64 monitor_page2;
59646a97191SGreg Kroah-Hartman } __packed;
59746a97191SGreg Kroah-Hartman 
5985c23a1a5SDexuan Cui /* Hyper-V socket: guest's connect()-ing to host */
5995c23a1a5SDexuan Cui struct vmbus_channel_tl_connect_request {
6005c23a1a5SDexuan Cui 	struct vmbus_channel_message_header header;
6015c23a1a5SDexuan Cui 	uuid_le guest_endpoint_id;
6025c23a1a5SDexuan Cui 	uuid_le host_service_id;
6035c23a1a5SDexuan Cui } __packed;
6045c23a1a5SDexuan Cui 
60546a97191SGreg Kroah-Hartman struct vmbus_channel_version_response {
60646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
6071508d811SK. Y. Srinivasan 	u8 version_supported;
60846a97191SGreg Kroah-Hartman } __packed;
60946a97191SGreg Kroah-Hartman 
61046a97191SGreg Kroah-Hartman enum vmbus_channel_state {
61146a97191SGreg Kroah-Hartman 	CHANNEL_OFFER_STATE,
61246a97191SGreg Kroah-Hartman 	CHANNEL_OPENING_STATE,
61346a97191SGreg Kroah-Hartman 	CHANNEL_OPEN_STATE,
614e68d2971SK. Y. Srinivasan 	CHANNEL_OPENED_STATE,
61546a97191SGreg Kroah-Hartman };
61646a97191SGreg Kroah-Hartman 
61746a97191SGreg Kroah-Hartman /*
61846a97191SGreg Kroah-Hartman  * Represents each channel msg on the vmbus connection This is a
61946a97191SGreg Kroah-Hartman  * variable-size data structure depending on the msg type itself
62046a97191SGreg Kroah-Hartman  */
62146a97191SGreg Kroah-Hartman struct vmbus_channel_msginfo {
62246a97191SGreg Kroah-Hartman 	/* Bookkeeping stuff */
62346a97191SGreg Kroah-Hartman 	struct list_head msglistentry;
62446a97191SGreg Kroah-Hartman 
62546a97191SGreg Kroah-Hartman 	/* So far, this is only used to handle gpadl body message */
62646a97191SGreg Kroah-Hartman 	struct list_head submsglist;
62746a97191SGreg Kroah-Hartman 
62846a97191SGreg Kroah-Hartman 	/* Synchronize the request/response if needed */
62946a97191SGreg Kroah-Hartman 	struct completion  waitevent;
63046a97191SGreg Kroah-Hartman 	union {
63146a97191SGreg Kroah-Hartman 		struct vmbus_channel_version_supported version_supported;
63246a97191SGreg Kroah-Hartman 		struct vmbus_channel_open_result open_result;
63346a97191SGreg Kroah-Hartman 		struct vmbus_channel_gpadl_torndown gpadl_torndown;
63446a97191SGreg Kroah-Hartman 		struct vmbus_channel_gpadl_created gpadl_created;
63546a97191SGreg Kroah-Hartman 		struct vmbus_channel_version_response version_response;
63646a97191SGreg Kroah-Hartman 	} response;
63746a97191SGreg Kroah-Hartman 
63846a97191SGreg Kroah-Hartman 	u32 msgsize;
63946a97191SGreg Kroah-Hartman 	/*
64046a97191SGreg Kroah-Hartman 	 * The channel message that goes out on the "wire".
64146a97191SGreg Kroah-Hartman 	 * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header
64246a97191SGreg Kroah-Hartman 	 */
64346a97191SGreg Kroah-Hartman 	unsigned char msg[0];
64446a97191SGreg Kroah-Hartman };
64546a97191SGreg Kroah-Hartman 
64646a97191SGreg Kroah-Hartman struct vmbus_close_msg {
64746a97191SGreg Kroah-Hartman 	struct vmbus_channel_msginfo info;
64846a97191SGreg Kroah-Hartman 	struct vmbus_channel_close_channel msg;
64946a97191SGreg Kroah-Hartman };
65046a97191SGreg Kroah-Hartman 
651b3bf60c7SK. Y. Srinivasan /* Define connection identifier type. */
652b3bf60c7SK. Y. Srinivasan union hv_connection_id {
653b3bf60c7SK. Y. Srinivasan 	u32 asu32;
654b3bf60c7SK. Y. Srinivasan 	struct {
655b3bf60c7SK. Y. Srinivasan 		u32 id:24;
656b3bf60c7SK. Y. Srinivasan 		u32 reserved:8;
657b3bf60c7SK. Y. Srinivasan 	} u;
658b3bf60c7SK. Y. Srinivasan };
659b3bf60c7SK. Y. Srinivasan 
660b3bf60c7SK. Y. Srinivasan /* Definition of the hv_signal_event hypercall input structure. */
661b3bf60c7SK. Y. Srinivasan struct hv_input_signal_event {
662b3bf60c7SK. Y. Srinivasan 	union hv_connection_id connectionid;
663b3bf60c7SK. Y. Srinivasan 	u16 flag_number;
664b3bf60c7SK. Y. Srinivasan 	u16 rsvdz;
665b3bf60c7SK. Y. Srinivasan };
666b3bf60c7SK. Y. Srinivasan 
667b3bf60c7SK. Y. Srinivasan struct hv_input_signal_event_buffer {
668b3bf60c7SK. Y. Srinivasan 	u64 align8;
669b3bf60c7SK. Y. Srinivasan 	struct hv_input_signal_event event;
670b3bf60c7SK. Y. Srinivasan };
671b3bf60c7SK. Y. Srinivasan 
6728599846dSK. Y. Srinivasan enum hv_signal_policy {
6738599846dSK. Y. Srinivasan 	HV_SIGNAL_POLICY_DEFAULT = 0,
6748599846dSK. Y. Srinivasan 	HV_SIGNAL_POLICY_EXPLICIT,
6758599846dSK. Y. Srinivasan };
6768599846dSK. Y. Srinivasan 
6777047f17dSK. Y. Srinivasan enum vmbus_device_type {
6787047f17dSK. Y. Srinivasan 	HV_IDE = 0,
6797047f17dSK. Y. Srinivasan 	HV_SCSI,
6807047f17dSK. Y. Srinivasan 	HV_FC,
6817047f17dSK. Y. Srinivasan 	HV_NIC,
6827047f17dSK. Y. Srinivasan 	HV_ND,
6837047f17dSK. Y. Srinivasan 	HV_PCIE,
6847047f17dSK. Y. Srinivasan 	HV_FB,
6857047f17dSK. Y. Srinivasan 	HV_KBD,
6867047f17dSK. Y. Srinivasan 	HV_MOUSE,
6877047f17dSK. Y. Srinivasan 	HV_KVP,
6887047f17dSK. Y. Srinivasan 	HV_TS,
6897047f17dSK. Y. Srinivasan 	HV_HB,
6907047f17dSK. Y. Srinivasan 	HV_SHUTDOWN,
6917047f17dSK. Y. Srinivasan 	HV_FCOPY,
6927047f17dSK. Y. Srinivasan 	HV_BACKUP,
6937047f17dSK. Y. Srinivasan 	HV_DM,
6947047f17dSK. Y. Srinivasan 	HV_UNKOWN,
6957047f17dSK. Y. Srinivasan };
6967047f17dSK. Y. Srinivasan 
6977047f17dSK. Y. Srinivasan struct vmbus_device {
6987047f17dSK. Y. Srinivasan 	u16  dev_type;
6997047f17dSK. Y. Srinivasan 	uuid_le guid;
7007047f17dSK. Y. Srinivasan 	bool perf_device;
7017047f17dSK. Y. Srinivasan };
7027047f17dSK. Y. Srinivasan 
70346a97191SGreg Kroah-Hartman struct vmbus_channel {
704bc63b6f6SVitaly Kuznetsov 	/* Unique channel id */
705bc63b6f6SVitaly Kuznetsov 	int id;
706bc63b6f6SVitaly Kuznetsov 
70746a97191SGreg Kroah-Hartman 	struct list_head listentry;
70846a97191SGreg Kroah-Hartman 
70946a97191SGreg Kroah-Hartman 	struct hv_device *device_obj;
71046a97191SGreg Kroah-Hartman 
71146a97191SGreg Kroah-Hartman 	enum vmbus_channel_state state;
71246a97191SGreg Kroah-Hartman 
71346a97191SGreg Kroah-Hartman 	struct vmbus_channel_offer_channel offermsg;
71446a97191SGreg Kroah-Hartman 	/*
71546a97191SGreg Kroah-Hartman 	 * These are based on the OfferMsg.MonitorId.
71646a97191SGreg Kroah-Hartman 	 * Save it here for easy access.
71746a97191SGreg Kroah-Hartman 	 */
71846a97191SGreg Kroah-Hartman 	u8 monitor_grp;
71946a97191SGreg Kroah-Hartman 	u8 monitor_bit;
72046a97191SGreg Kroah-Hartman 
721c3582a2cSHaiyang Zhang 	bool rescind; /* got rescind msg */
722c3582a2cSHaiyang Zhang 
72346a97191SGreg Kroah-Hartman 	u32 ringbuffer_gpadlhandle;
72446a97191SGreg Kroah-Hartman 
72546a97191SGreg Kroah-Hartman 	/* Allocated memory for ring buffer */
72646a97191SGreg Kroah-Hartman 	void *ringbuffer_pages;
72746a97191SGreg Kroah-Hartman 	u32 ringbuffer_pagecount;
72846a97191SGreg Kroah-Hartman 	struct hv_ring_buffer_info outbound;	/* send to parent */
72946a97191SGreg Kroah-Hartman 	struct hv_ring_buffer_info inbound;	/* receive from parent */
73046a97191SGreg Kroah-Hartman 	spinlock_t inbound_lock;
73146a97191SGreg Kroah-Hartman 
73246a97191SGreg Kroah-Hartman 	struct vmbus_close_msg close_msg;
73346a97191SGreg Kroah-Hartman 
73446a97191SGreg Kroah-Hartman 	/* Channel callback are invoked in this workqueue context */
73546a97191SGreg Kroah-Hartman 	/* HANDLE dataWorkQueue; */
73646a97191SGreg Kroah-Hartman 
73746a97191SGreg Kroah-Hartman 	void (*onchannel_callback)(void *context);
73846a97191SGreg Kroah-Hartman 	void *channel_callback_context;
739132368bdSK. Y. Srinivasan 
740132368bdSK. Y. Srinivasan 	/*
741132368bdSK. Y. Srinivasan 	 * A channel can be marked for efficient (batched)
742132368bdSK. Y. Srinivasan 	 * reading:
743132368bdSK. Y. Srinivasan 	 * If batched_reading is set to "true", we read until the
744132368bdSK. Y. Srinivasan 	 * channel is empty and hold off interrupts from the host
745132368bdSK. Y. Srinivasan 	 * during the entire read process.
746132368bdSK. Y. Srinivasan 	 * If batched_reading is set to "false", the client is not
747132368bdSK. Y. Srinivasan 	 * going to perform batched reading.
748132368bdSK. Y. Srinivasan 	 *
749132368bdSK. Y. Srinivasan 	 * By default we will enable batched reading; specific
750132368bdSK. Y. Srinivasan 	 * drivers that don't want this behavior can turn it off.
751132368bdSK. Y. Srinivasan 	 */
752132368bdSK. Y. Srinivasan 
753132368bdSK. Y. Srinivasan 	bool batched_reading;
754b3bf60c7SK. Y. Srinivasan 
755b3bf60c7SK. Y. Srinivasan 	bool is_dedicated_interrupt;
756b3bf60c7SK. Y. Srinivasan 	struct hv_input_signal_event_buffer sig_buf;
757b3bf60c7SK. Y. Srinivasan 	struct hv_input_signal_event *sig_event;
758abbf3b2aSK. Y. Srinivasan 
759abbf3b2aSK. Y. Srinivasan 	/*
760abbf3b2aSK. Y. Srinivasan 	 * Starting with win8, this field will be used to specify
761abbf3b2aSK. Y. Srinivasan 	 * the target virtual processor on which to deliver the interrupt for
762abbf3b2aSK. Y. Srinivasan 	 * the host to guest communication.
763abbf3b2aSK. Y. Srinivasan 	 * Prior to win8, incoming channel interrupts would only
764abbf3b2aSK. Y. Srinivasan 	 * be delivered on cpu 0. Setting this value to 0 would
765abbf3b2aSK. Y. Srinivasan 	 * preserve the earlier behavior.
766abbf3b2aSK. Y. Srinivasan 	 */
767abbf3b2aSK. Y. Srinivasan 	u32 target_vp;
768d3ba720dSK. Y. Srinivasan 	/* The corresponding CPUID in the guest */
769d3ba720dSK. Y. Srinivasan 	u32 target_cpu;
770e68d2971SK. Y. Srinivasan 	/*
7711f656ff3SK. Y. Srinivasan 	 * State to manage the CPU affiliation of channels.
7721f656ff3SK. Y. Srinivasan 	 */
7733b71107dSDexuan Cui 	struct cpumask alloced_cpus_in_node;
7741f656ff3SK. Y. Srinivasan 	int numa_node;
7751f656ff3SK. Y. Srinivasan 	/*
776e68d2971SK. Y. Srinivasan 	 * Support for sub-channels. For high performance devices,
777e68d2971SK. Y. Srinivasan 	 * it will be useful to have multiple sub-channels to support
778e68d2971SK. Y. Srinivasan 	 * a scalable communication infrastructure with the host.
779e68d2971SK. Y. Srinivasan 	 * The support for sub-channels is implemented as an extention
780e68d2971SK. Y. Srinivasan 	 * to the current infrastructure.
781e68d2971SK. Y. Srinivasan 	 * The initial offer is considered the primary channel and this
782e68d2971SK. Y. Srinivasan 	 * offer message will indicate if the host supports sub-channels.
783e68d2971SK. Y. Srinivasan 	 * The guest is free to ask for sub-channels to be offerred and can
784e68d2971SK. Y. Srinivasan 	 * open these sub-channels as a normal "primary" channel. However,
785e68d2971SK. Y. Srinivasan 	 * all sub-channels will have the same type and instance guids as the
786e68d2971SK. Y. Srinivasan 	 * primary channel. Requests sent on a given channel will result in a
787e68d2971SK. Y. Srinivasan 	 * response on the same channel.
788e68d2971SK. Y. Srinivasan 	 */
789e68d2971SK. Y. Srinivasan 
790e68d2971SK. Y. Srinivasan 	/*
791e68d2971SK. Y. Srinivasan 	 * Sub-channel creation callback. This callback will be called in
792e68d2971SK. Y. Srinivasan 	 * process context when a sub-channel offer is received from the host.
793e68d2971SK. Y. Srinivasan 	 * The guest can open the sub-channel in the context of this callback.
794e68d2971SK. Y. Srinivasan 	 */
795e68d2971SK. Y. Srinivasan 	void (*sc_creation_callback)(struct vmbus_channel *new_sc);
796e68d2971SK. Y. Srinivasan 
79767fae053SVitaly Kuznetsov 	/*
798499e8401SDexuan Cui 	 * Channel rescind callback. Some channels (the hvsock ones), need to
799499e8401SDexuan Cui 	 * register a callback which is invoked in vmbus_onoffer_rescind().
800499e8401SDexuan Cui 	 */
801499e8401SDexuan Cui 	void (*chn_rescind_callback)(struct vmbus_channel *channel);
802499e8401SDexuan Cui 
803499e8401SDexuan Cui 	/*
80467fae053SVitaly Kuznetsov 	 * The spinlock to protect the structure. It is being used to protect
80567fae053SVitaly Kuznetsov 	 * test-and-set access to various attributes of the structure as well
80667fae053SVitaly Kuznetsov 	 * as all sc_list operations.
80767fae053SVitaly Kuznetsov 	 */
80867fae053SVitaly Kuznetsov 	spinlock_t lock;
809e68d2971SK. Y. Srinivasan 	/*
810e68d2971SK. Y. Srinivasan 	 * All Sub-channels of a primary channel are linked here.
811e68d2971SK. Y. Srinivasan 	 */
812e68d2971SK. Y. Srinivasan 	struct list_head sc_list;
813e68d2971SK. Y. Srinivasan 	/*
814fea844a2SVitaly Kuznetsov 	 * Current number of sub-channels.
815fea844a2SVitaly Kuznetsov 	 */
816fea844a2SVitaly Kuznetsov 	int num_sc;
817fea844a2SVitaly Kuznetsov 	/*
818fea844a2SVitaly Kuznetsov 	 * Number of a sub-channel (position within sc_list) which is supposed
819fea844a2SVitaly Kuznetsov 	 * to be used as the next outgoing channel.
820fea844a2SVitaly Kuznetsov 	 */
821fea844a2SVitaly Kuznetsov 	int next_oc;
822fea844a2SVitaly Kuznetsov 	/*
823e68d2971SK. Y. Srinivasan 	 * The primary channel this sub-channel belongs to.
824e68d2971SK. Y. Srinivasan 	 * This will be NULL for the primary channel.
825e68d2971SK. Y. Srinivasan 	 */
826e68d2971SK. Y. Srinivasan 	struct vmbus_channel *primary_channel;
8278a7206a8SK. Y. Srinivasan 	/*
8288a7206a8SK. Y. Srinivasan 	 * Support per-channel state for use by vmbus drivers.
8298a7206a8SK. Y. Srinivasan 	 */
8308a7206a8SK. Y. Srinivasan 	void *per_channel_state;
8313a28fa35SK. Y. Srinivasan 	/*
8323a28fa35SK. Y. Srinivasan 	 * To support per-cpu lookup mapping of relid to channel,
8333a28fa35SK. Y. Srinivasan 	 * link up channels based on their CPU affinity.
8343a28fa35SK. Y. Srinivasan 	 */
8353a28fa35SK. Y. Srinivasan 	struct list_head percpu_list;
8368599846dSK. Y. Srinivasan 	/*
8378599846dSK. Y. Srinivasan 	 * Host signaling policy: The default policy will be
8388599846dSK. Y. Srinivasan 	 * based on the ring buffer state. We will also support
8398599846dSK. Y. Srinivasan 	 * a policy where the client driver can have explicit
8408599846dSK. Y. Srinivasan 	 * signaling control.
8418599846dSK. Y. Srinivasan 	 */
8428599846dSK. Y. Srinivasan 	enum hv_signal_policy  signal_policy;
843fe760e4dSK. Y. Srinivasan 	/*
844fe760e4dSK. Y. Srinivasan 	 * On the channel send side, many of the VMBUS
845fe760e4dSK. Y. Srinivasan 	 * device drivers explicity serialize access to the
846fe760e4dSK. Y. Srinivasan 	 * outgoing ring buffer. Give more control to the
847fe760e4dSK. Y. Srinivasan 	 * VMBUS device drivers in terms how to serialize
848fe760e4dSK. Y. Srinivasan 	 * accesss to the outgoing ring buffer.
849fe760e4dSK. Y. Srinivasan 	 * The default behavior will be to aquire the
850fe760e4dSK. Y. Srinivasan 	 * ring lock to preserve the current behavior.
851fe760e4dSK. Y. Srinivasan 	 */
852fe760e4dSK. Y. Srinivasan 	bool acquire_ring_lock;
853*3724287cSK. Y. Srinivasan 	/*
854*3724287cSK. Y. Srinivasan 	 * For performance critical channels (storage, networking
855*3724287cSK. Y. Srinivasan 	 * etc,), Hyper-V has a mechanism to enhance the throughput
856*3724287cSK. Y. Srinivasan 	 * at the expense of latency:
857*3724287cSK. Y. Srinivasan 	 * When the host is to be signaled, we just set a bit in a shared page
858*3724287cSK. Y. Srinivasan 	 * and this bit will be inspected by the hypervisor within a certain
859*3724287cSK. Y. Srinivasan 	 * window and if the bit is set, the host will be signaled. The window
860*3724287cSK. Y. Srinivasan 	 * of time is the monitor latency - currently around 100 usecs. This
861*3724287cSK. Y. Srinivasan 	 * mechanism improves throughput by:
862*3724287cSK. Y. Srinivasan 	 *
863*3724287cSK. Y. Srinivasan 	 * A) Making the host more efficient - each time it wakes up,
864*3724287cSK. Y. Srinivasan 	 *    potentially it will process morev number of packets. The
865*3724287cSK. Y. Srinivasan 	 *    monitor latency allows a batch to build up.
866*3724287cSK. Y. Srinivasan 	 * B) By deferring the hypercall to signal, we will also minimize
867*3724287cSK. Y. Srinivasan 	 *    the interrupts.
868*3724287cSK. Y. Srinivasan 	 *
869*3724287cSK. Y. Srinivasan 	 * Clearly, these optimizations improve throughput at the expense of
870*3724287cSK. Y. Srinivasan 	 * latency. Furthermore, since the channel is shared for both
871*3724287cSK. Y. Srinivasan 	 * control and data messages, control messages currently suffer
872*3724287cSK. Y. Srinivasan 	 * unnecessary latency adversley impacting performance and boot
873*3724287cSK. Y. Srinivasan 	 * time. To fix this issue, permit tagging the channel as being
874*3724287cSK. Y. Srinivasan 	 * in "low latency" mode. In this mode, we will bypass the monitor
875*3724287cSK. Y. Srinivasan 	 * mechanism.
876*3724287cSK. Y. Srinivasan 	 */
877*3724287cSK. Y. Srinivasan 	bool low_latency;
878fe760e4dSK. Y. Srinivasan 
87946a97191SGreg Kroah-Hartman };
88046a97191SGreg Kroah-Hartman 
881fe760e4dSK. Y. Srinivasan static inline void set_channel_lock_state(struct vmbus_channel *c, bool state)
882fe760e4dSK. Y. Srinivasan {
883fe760e4dSK. Y. Srinivasan 	c->acquire_ring_lock = state;
884fe760e4dSK. Y. Srinivasan }
885fe760e4dSK. Y. Srinivasan 
886e8d6ca02SDexuan Cui static inline bool is_hvsock_channel(const struct vmbus_channel *c)
887e8d6ca02SDexuan Cui {
888e8d6ca02SDexuan Cui 	return !!(c->offermsg.offer.chn_flags &
889e8d6ca02SDexuan Cui 		  VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER);
890e8d6ca02SDexuan Cui }
891e8d6ca02SDexuan Cui 
8928599846dSK. Y. Srinivasan static inline void set_channel_signal_state(struct vmbus_channel *c,
8938599846dSK. Y. Srinivasan 					    enum hv_signal_policy policy)
8948599846dSK. Y. Srinivasan {
8958599846dSK. Y. Srinivasan 	c->signal_policy = policy;
8968599846dSK. Y. Srinivasan }
8978599846dSK. Y. Srinivasan 
898132368bdSK. Y. Srinivasan static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
899132368bdSK. Y. Srinivasan {
900132368bdSK. Y. Srinivasan 	c->batched_reading = state;
901132368bdSK. Y. Srinivasan }
902132368bdSK. Y. Srinivasan 
9038a7206a8SK. Y. Srinivasan static inline void set_per_channel_state(struct vmbus_channel *c, void *s)
9048a7206a8SK. Y. Srinivasan {
9058a7206a8SK. Y. Srinivasan 	c->per_channel_state = s;
9068a7206a8SK. Y. Srinivasan }
9078a7206a8SK. Y. Srinivasan 
9088a7206a8SK. Y. Srinivasan static inline void *get_per_channel_state(struct vmbus_channel *c)
9098a7206a8SK. Y. Srinivasan {
9108a7206a8SK. Y. Srinivasan 	return c->per_channel_state;
9118a7206a8SK. Y. Srinivasan }
9128a7206a8SK. Y. Srinivasan 
9133c75354dSDexuan Cui static inline void set_channel_pending_send_size(struct vmbus_channel *c,
9143c75354dSDexuan Cui 						 u32 size)
9153c75354dSDexuan Cui {
9163c75354dSDexuan Cui 	c->outbound.ring_buffer->pending_send_sz = size;
9173c75354dSDexuan Cui }
9183c75354dSDexuan Cui 
919*3724287cSK. Y. Srinivasan static inline void set_low_latency_mode(struct vmbus_channel *c)
920*3724287cSK. Y. Srinivasan {
921*3724287cSK. Y. Srinivasan 	c->low_latency = true;
922*3724287cSK. Y. Srinivasan }
923*3724287cSK. Y. Srinivasan 
924*3724287cSK. Y. Srinivasan static inline void clear_low_latency_mode(struct vmbus_channel *c)
925*3724287cSK. Y. Srinivasan {
926*3724287cSK. Y. Srinivasan 	c->low_latency = false;
927*3724287cSK. Y. Srinivasan }
928*3724287cSK. Y. Srinivasan 
92946a97191SGreg Kroah-Hartman void vmbus_onmessage(void *context);
93046a97191SGreg Kroah-Hartman 
93146a97191SGreg Kroah-Hartman int vmbus_request_offers(void);
93246a97191SGreg Kroah-Hartman 
933e68d2971SK. Y. Srinivasan /*
934e68d2971SK. Y. Srinivasan  * APIs for managing sub-channels.
935e68d2971SK. Y. Srinivasan  */
936e68d2971SK. Y. Srinivasan 
937e68d2971SK. Y. Srinivasan void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
938e68d2971SK. Y. Srinivasan 			void (*sc_cr_cb)(struct vmbus_channel *new_sc));
939e68d2971SK. Y. Srinivasan 
940499e8401SDexuan Cui void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
941499e8401SDexuan Cui 		void (*chn_rescind_cb)(struct vmbus_channel *));
942499e8401SDexuan Cui 
943e68d2971SK. Y. Srinivasan /*
944e68d2971SK. Y. Srinivasan  * Retrieve the (sub) channel on which to send an outgoing request.
945e68d2971SK. Y. Srinivasan  * When a primary channel has multiple sub-channels, we choose a
946e68d2971SK. Y. Srinivasan  * channel whose VCPU binding is closest to the VCPU on which
947e68d2971SK. Y. Srinivasan  * this call is being made.
948e68d2971SK. Y. Srinivasan  */
949e68d2971SK. Y. Srinivasan struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary);
950e68d2971SK. Y. Srinivasan 
951e68d2971SK. Y. Srinivasan /*
952e68d2971SK. Y. Srinivasan  * Check if sub-channels have already been offerred. This API will be useful
953e68d2971SK. Y. Srinivasan  * when the driver is unloaded after establishing sub-channels. In this case,
954e68d2971SK. Y. Srinivasan  * when the driver is re-loaded, the driver would have to check if the
955e68d2971SK. Y. Srinivasan  * subchannels have already been established before attempting to request
956e68d2971SK. Y. Srinivasan  * the creation of sub-channels.
957e68d2971SK. Y. Srinivasan  * This function returns TRUE to indicate that subchannels have already been
958e68d2971SK. Y. Srinivasan  * created.
959e68d2971SK. Y. Srinivasan  * This function should be invoked after setting the callback function for
960e68d2971SK. Y. Srinivasan  * sub-channel creation.
961e68d2971SK. Y. Srinivasan  */
962e68d2971SK. Y. Srinivasan bool vmbus_are_subchannels_present(struct vmbus_channel *primary);
963e68d2971SK. Y. Srinivasan 
96446a97191SGreg Kroah-Hartman /* The format must be the same as struct vmdata_gpa_direct */
96546a97191SGreg Kroah-Hartman struct vmbus_channel_packet_page_buffer {
96646a97191SGreg Kroah-Hartman 	u16 type;
96746a97191SGreg Kroah-Hartman 	u16 dataoffset8;
96846a97191SGreg Kroah-Hartman 	u16 length8;
96946a97191SGreg Kroah-Hartman 	u16 flags;
97046a97191SGreg Kroah-Hartman 	u64 transactionid;
97146a97191SGreg Kroah-Hartman 	u32 reserved;
97246a97191SGreg Kroah-Hartman 	u32 rangecount;
97346a97191SGreg Kroah-Hartman 	struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT];
97446a97191SGreg Kroah-Hartman } __packed;
97546a97191SGreg Kroah-Hartman 
97646a97191SGreg Kroah-Hartman /* The format must be the same as struct vmdata_gpa_direct */
97746a97191SGreg Kroah-Hartman struct vmbus_channel_packet_multipage_buffer {
97846a97191SGreg Kroah-Hartman 	u16 type;
97946a97191SGreg Kroah-Hartman 	u16 dataoffset8;
98046a97191SGreg Kroah-Hartman 	u16 length8;
98146a97191SGreg Kroah-Hartman 	u16 flags;
98246a97191SGreg Kroah-Hartman 	u64 transactionid;
98346a97191SGreg Kroah-Hartman 	u32 reserved;
98446a97191SGreg Kroah-Hartman 	u32 rangecount;		/* Always 1 in this case */
98546a97191SGreg Kroah-Hartman 	struct hv_multipage_buffer range;
98646a97191SGreg Kroah-Hartman } __packed;
98746a97191SGreg Kroah-Hartman 
988d61031eeSK. Y. Srinivasan /* The format must be the same as struct vmdata_gpa_direct */
989d61031eeSK. Y. Srinivasan struct vmbus_packet_mpb_array {
990d61031eeSK. Y. Srinivasan 	u16 type;
991d61031eeSK. Y. Srinivasan 	u16 dataoffset8;
992d61031eeSK. Y. Srinivasan 	u16 length8;
993d61031eeSK. Y. Srinivasan 	u16 flags;
994d61031eeSK. Y. Srinivasan 	u64 transactionid;
995d61031eeSK. Y. Srinivasan 	u32 reserved;
996d61031eeSK. Y. Srinivasan 	u32 rangecount;         /* Always 1 in this case */
997d61031eeSK. Y. Srinivasan 	struct hv_mpb_array range;
998d61031eeSK. Y. Srinivasan } __packed;
999d61031eeSK. Y. Srinivasan 
100046a97191SGreg Kroah-Hartman 
100146a97191SGreg Kroah-Hartman extern int vmbus_open(struct vmbus_channel *channel,
100246a97191SGreg Kroah-Hartman 			    u32 send_ringbuffersize,
100346a97191SGreg Kroah-Hartman 			    u32 recv_ringbuffersize,
100446a97191SGreg Kroah-Hartman 			    void *userdata,
100546a97191SGreg Kroah-Hartman 			    u32 userdatalen,
100646a97191SGreg Kroah-Hartman 			    void(*onchannel_callback)(void *context),
100746a97191SGreg Kroah-Hartman 			    void *context);
100846a97191SGreg Kroah-Hartman 
100946a97191SGreg Kroah-Hartman extern void vmbus_close(struct vmbus_channel *channel);
101046a97191SGreg Kroah-Hartman 
101146a97191SGreg Kroah-Hartman extern int vmbus_sendpacket(struct vmbus_channel *channel,
1012011a7c3cSK. Y. Srinivasan 				  void *buffer,
101346a97191SGreg Kroah-Hartman 				  u32 bufferLen,
101446a97191SGreg Kroah-Hartman 				  u64 requestid,
101546a97191SGreg Kroah-Hartman 				  enum vmbus_packet_type type,
101646a97191SGreg Kroah-Hartman 				  u32 flags);
101746a97191SGreg Kroah-Hartman 
1018e9395e3fSK. Y. Srinivasan extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel,
1019e9395e3fSK. Y. Srinivasan 				  void *buffer,
1020e9395e3fSK. Y. Srinivasan 				  u32 bufferLen,
1021e9395e3fSK. Y. Srinivasan 				  u64 requestid,
1022e9395e3fSK. Y. Srinivasan 				  enum vmbus_packet_type type,
1023e9395e3fSK. Y. Srinivasan 				  u32 flags,
1024e9395e3fSK. Y. Srinivasan 				  bool kick_q);
1025e9395e3fSK. Y. Srinivasan 
102646a97191SGreg Kroah-Hartman extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
102746a97191SGreg Kroah-Hartman 					    struct hv_page_buffer pagebuffers[],
102846a97191SGreg Kroah-Hartman 					    u32 pagecount,
102946a97191SGreg Kroah-Hartman 					    void *buffer,
103046a97191SGreg Kroah-Hartman 					    u32 bufferlen,
103146a97191SGreg Kroah-Hartman 					    u64 requestid);
103246a97191SGreg Kroah-Hartman 
103387e93d61SK. Y. Srinivasan extern int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
103487e93d61SK. Y. Srinivasan 					   struct hv_page_buffer pagebuffers[],
103587e93d61SK. Y. Srinivasan 					   u32 pagecount,
103687e93d61SK. Y. Srinivasan 					   void *buffer,
103787e93d61SK. Y. Srinivasan 					   u32 bufferlen,
103887e93d61SK. Y. Srinivasan 					   u64 requestid,
103987e93d61SK. Y. Srinivasan 					   u32 flags,
104087e93d61SK. Y. Srinivasan 					   bool kick_q);
104187e93d61SK. Y. Srinivasan 
104246a97191SGreg Kroah-Hartman extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
104346a97191SGreg Kroah-Hartman 					struct hv_multipage_buffer *mpb,
104446a97191SGreg Kroah-Hartman 					void *buffer,
104546a97191SGreg Kroah-Hartman 					u32 bufferlen,
104646a97191SGreg Kroah-Hartman 					u64 requestid);
104746a97191SGreg Kroah-Hartman 
1048d61031eeSK. Y. Srinivasan extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
1049d61031eeSK. Y. Srinivasan 				     struct vmbus_packet_mpb_array *mpb,
1050d61031eeSK. Y. Srinivasan 				     u32 desc_size,
1051d61031eeSK. Y. Srinivasan 				     void *buffer,
1052d61031eeSK. Y. Srinivasan 				     u32 bufferlen,
1053d61031eeSK. Y. Srinivasan 				     u64 requestid);
1054d61031eeSK. Y. Srinivasan 
105546a97191SGreg Kroah-Hartman extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
105646a97191SGreg Kroah-Hartman 				      void *kbuffer,
105746a97191SGreg Kroah-Hartman 				      u32 size,
105846a97191SGreg Kroah-Hartman 				      u32 *gpadl_handle);
105946a97191SGreg Kroah-Hartman 
106046a97191SGreg Kroah-Hartman extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
106146a97191SGreg Kroah-Hartman 				     u32 gpadl_handle);
106246a97191SGreg Kroah-Hartman 
106346a97191SGreg Kroah-Hartman extern int vmbus_recvpacket(struct vmbus_channel *channel,
106446a97191SGreg Kroah-Hartman 				  void *buffer,
106546a97191SGreg Kroah-Hartman 				  u32 bufferlen,
106646a97191SGreg Kroah-Hartman 				  u32 *buffer_actual_len,
106746a97191SGreg Kroah-Hartman 				  u64 *requestid);
106846a97191SGreg Kroah-Hartman 
106946a97191SGreg Kroah-Hartman extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
107046a97191SGreg Kroah-Hartman 				     void *buffer,
107146a97191SGreg Kroah-Hartman 				     u32 bufferlen,
107246a97191SGreg Kroah-Hartman 				     u32 *buffer_actual_len,
107346a97191SGreg Kroah-Hartman 				     u64 *requestid);
107446a97191SGreg Kroah-Hartman 
107546a97191SGreg Kroah-Hartman 
107646a97191SGreg Kroah-Hartman extern void vmbus_ontimer(unsigned long data);
107746a97191SGreg Kroah-Hartman 
107846a97191SGreg Kroah-Hartman /* Base driver object */
107946a97191SGreg Kroah-Hartman struct hv_driver {
108046a97191SGreg Kroah-Hartman 	const char *name;
108146a97191SGreg Kroah-Hartman 
10828981da32SDexuan Cui 	/*
10838981da32SDexuan Cui 	 * A hvsock offer, which has a VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER
10848981da32SDexuan Cui 	 * channel flag, actually doesn't mean a synthetic device because the
10858981da32SDexuan Cui 	 * offer's if_type/if_instance can change for every new hvsock
10868981da32SDexuan Cui 	 * connection.
10878981da32SDexuan Cui 	 *
10888981da32SDexuan Cui 	 * However, to facilitate the notification of new-offer/rescind-offer
10898981da32SDexuan Cui 	 * from vmbus driver to hvsock driver, we can handle hvsock offer as
10908981da32SDexuan Cui 	 * a special vmbus device, and hence we need the below flag to
10918981da32SDexuan Cui 	 * indicate if the driver is the hvsock driver or not: we need to
10928981da32SDexuan Cui 	 * specially treat the hvosck offer & driver in vmbus_match().
10938981da32SDexuan Cui 	 */
10948981da32SDexuan Cui 	bool hvsock;
10958981da32SDexuan Cui 
109646a97191SGreg Kroah-Hartman 	/* the device type supported by this driver */
109746a97191SGreg Kroah-Hartman 	uuid_le dev_type;
109846a97191SGreg Kroah-Hartman 	const struct hv_vmbus_device_id *id_table;
109946a97191SGreg Kroah-Hartman 
110046a97191SGreg Kroah-Hartman 	struct device_driver driver;
110146a97191SGreg Kroah-Hartman 
110246a97191SGreg Kroah-Hartman 	int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *);
110346a97191SGreg Kroah-Hartman 	int (*remove)(struct hv_device *);
110446a97191SGreg Kroah-Hartman 	void (*shutdown)(struct hv_device *);
110546a97191SGreg Kroah-Hartman 
110646a97191SGreg Kroah-Hartman };
110746a97191SGreg Kroah-Hartman 
110846a97191SGreg Kroah-Hartman /* Base device object */
110946a97191SGreg Kroah-Hartman struct hv_device {
111046a97191SGreg Kroah-Hartman 	/* the device type id of this device */
111146a97191SGreg Kroah-Hartman 	uuid_le dev_type;
111246a97191SGreg Kroah-Hartman 
111346a97191SGreg Kroah-Hartman 	/* the device instance id of this device */
111446a97191SGreg Kroah-Hartman 	uuid_le dev_instance;
11157047f17dSK. Y. Srinivasan 	u16 vendor_id;
11167047f17dSK. Y. Srinivasan 	u16 device_id;
111746a97191SGreg Kroah-Hartman 
111846a97191SGreg Kroah-Hartman 	struct device device;
111946a97191SGreg Kroah-Hartman 
112046a97191SGreg Kroah-Hartman 	struct vmbus_channel *channel;
112146a97191SGreg Kroah-Hartman };
112246a97191SGreg Kroah-Hartman 
112346a97191SGreg Kroah-Hartman 
112446a97191SGreg Kroah-Hartman static inline struct hv_device *device_to_hv_device(struct device *d)
112546a97191SGreg Kroah-Hartman {
112646a97191SGreg Kroah-Hartman 	return container_of(d, struct hv_device, device);
112746a97191SGreg Kroah-Hartman }
112846a97191SGreg Kroah-Hartman 
112946a97191SGreg Kroah-Hartman static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
113046a97191SGreg Kroah-Hartman {
113146a97191SGreg Kroah-Hartman 	return container_of(d, struct hv_driver, driver);
113246a97191SGreg Kroah-Hartman }
113346a97191SGreg Kroah-Hartman 
113446a97191SGreg Kroah-Hartman static inline void hv_set_drvdata(struct hv_device *dev, void *data)
113546a97191SGreg Kroah-Hartman {
113646a97191SGreg Kroah-Hartman 	dev_set_drvdata(&dev->device, data);
113746a97191SGreg Kroah-Hartman }
113846a97191SGreg Kroah-Hartman 
113946a97191SGreg Kroah-Hartman static inline void *hv_get_drvdata(struct hv_device *dev)
114046a97191SGreg Kroah-Hartman {
114146a97191SGreg Kroah-Hartman 	return dev_get_drvdata(&dev->device);
114246a97191SGreg Kroah-Hartman }
114346a97191SGreg Kroah-Hartman 
114446a97191SGreg Kroah-Hartman /* Vmbus interface */
114546a97191SGreg Kroah-Hartman #define vmbus_driver_register(driver)	\
114646a97191SGreg Kroah-Hartman 	__vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
114746a97191SGreg Kroah-Hartman int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
114846a97191SGreg Kroah-Hartman 					 struct module *owner,
114946a97191SGreg Kroah-Hartman 					 const char *mod_name);
115046a97191SGreg Kroah-Hartman void vmbus_driver_unregister(struct hv_driver *hv_driver);
115146a97191SGreg Kroah-Hartman 
115285d9aa70SDexuan Cui void vmbus_hvsock_device_unregister(struct vmbus_channel *channel);
115385d9aa70SDexuan Cui 
115435464483SJake Oshins int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
115535464483SJake Oshins 			resource_size_t min, resource_size_t max,
115635464483SJake Oshins 			resource_size_t size, resource_size_t align,
115735464483SJake Oshins 			bool fb_overlap_ok);
115897fb77dcSJake Oshins void vmbus_free_mmio(resource_size_t start, resource_size_t size);
1159619848bdSJake Oshins int vmbus_cpu_number_to_vp_number(int cpu_number);
1160a108393dSJake Oshins u64 hv_do_hypercall(u64 control, void *input, void *output);
1161619848bdSJake Oshins 
116246a97191SGreg Kroah-Hartman /*
11637fb96565SK. Y. Srinivasan  * GUID definitions of various offer types - services offered to the guest.
11647fb96565SK. Y. Srinivasan  */
11657fb96565SK. Y. Srinivasan 
11667fb96565SK. Y. Srinivasan /*
11677fb96565SK. Y. Srinivasan  * Network GUID
11687fb96565SK. Y. Srinivasan  * {f8615163-df3e-46c5-913f-f2d2f965ed0e}
11697fb96565SK. Y. Srinivasan  */
11707fb96565SK. Y. Srinivasan #define HV_NIC_GUID \
1171af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xf8615163, 0xdf3e, 0x46c5, 0x91, 0x3f, \
1172af3ff643SK. Y. Srinivasan 			0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e)
11737fb96565SK. Y. Srinivasan 
11747fb96565SK. Y. Srinivasan /*
11757fb96565SK. Y. Srinivasan  * IDE GUID
11767fb96565SK. Y. Srinivasan  * {32412632-86cb-44a2-9b5c-50d1417354f5}
11777fb96565SK. Y. Srinivasan  */
11787fb96565SK. Y. Srinivasan #define HV_IDE_GUID \
1179af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x32412632, 0x86cb, 0x44a2, 0x9b, 0x5c, \
1180af3ff643SK. Y. Srinivasan 			0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5)
11817fb96565SK. Y. Srinivasan 
11827fb96565SK. Y. Srinivasan /*
11837fb96565SK. Y. Srinivasan  * SCSI GUID
11847fb96565SK. Y. Srinivasan  * {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
11857fb96565SK. Y. Srinivasan  */
11867fb96565SK. Y. Srinivasan #define HV_SCSI_GUID \
1187af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xba6163d9, 0x04a1, 0x4d29, 0xb6, 0x05, \
1188af3ff643SK. Y. Srinivasan 			0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f)
11897fb96565SK. Y. Srinivasan 
11907fb96565SK. Y. Srinivasan /*
11917fb96565SK. Y. Srinivasan  * Shutdown GUID
11927fb96565SK. Y. Srinivasan  * {0e0b6031-5213-4934-818b-38d90ced39db}
11937fb96565SK. Y. Srinivasan  */
11947fb96565SK. Y. Srinivasan #define HV_SHUTDOWN_GUID \
1195af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x0e0b6031, 0x5213, 0x4934, 0x81, 0x8b, \
1196af3ff643SK. Y. Srinivasan 			0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb)
11977fb96565SK. Y. Srinivasan 
11987fb96565SK. Y. Srinivasan /*
11997fb96565SK. Y. Srinivasan  * Time Synch GUID
12007fb96565SK. Y. Srinivasan  * {9527E630-D0AE-497b-ADCE-E80AB0175CAF}
12017fb96565SK. Y. Srinivasan  */
12027fb96565SK. Y. Srinivasan #define HV_TS_GUID \
1203af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x9527e630, 0xd0ae, 0x497b, 0xad, 0xce, \
1204af3ff643SK. Y. Srinivasan 			0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
12057fb96565SK. Y. Srinivasan 
12067fb96565SK. Y. Srinivasan /*
12077fb96565SK. Y. Srinivasan  * Heartbeat GUID
12087fb96565SK. Y. Srinivasan  * {57164f39-9115-4e78-ab55-382f3bd5422d}
12097fb96565SK. Y. Srinivasan  */
12107fb96565SK. Y. Srinivasan #define HV_HEART_BEAT_GUID \
1211af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, \
1212af3ff643SK. Y. Srinivasan 			0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
12137fb96565SK. Y. Srinivasan 
12147fb96565SK. Y. Srinivasan /*
12157fb96565SK. Y. Srinivasan  * KVP GUID
12167fb96565SK. Y. Srinivasan  * {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}
12177fb96565SK. Y. Srinivasan  */
12187fb96565SK. Y. Srinivasan #define HV_KVP_GUID \
1219af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xa9a0f4e7, 0x5a45, 0x4d96, 0xb8, 0x27, \
1220af3ff643SK. Y. Srinivasan 			0x8a, 0x84, 0x1e, 0x8c, 0x03, 0xe6)
12217fb96565SK. Y. Srinivasan 
12227fb96565SK. Y. Srinivasan /*
12237fb96565SK. Y. Srinivasan  * Dynamic memory GUID
12247fb96565SK. Y. Srinivasan  * {525074dc-8985-46e2-8057-a307dc18a502}
12257fb96565SK. Y. Srinivasan  */
12267fb96565SK. Y. Srinivasan #define HV_DM_GUID \
1227af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x525074dc, 0x8985, 0x46e2, 0x80, 0x57, \
1228af3ff643SK. Y. Srinivasan 			0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02)
12297fb96565SK. Y. Srinivasan 
12307fb96565SK. Y. Srinivasan /*
12317fb96565SK. Y. Srinivasan  * Mouse GUID
12327fb96565SK. Y. Srinivasan  * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}
12337fb96565SK. Y. Srinivasan  */
12347fb96565SK. Y. Srinivasan #define HV_MOUSE_GUID \
1235af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xcfa8b69e, 0x5b4a, 0x4cc0, 0xb9, 0x8b, \
1236af3ff643SK. Y. Srinivasan 			0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a)
12377fb96565SK. Y. Srinivasan 
12387fb96565SK. Y. Srinivasan /*
12392048157aSDexuan Cui  * Keyboard GUID
12402048157aSDexuan Cui  * {f912ad6d-2b17-48ea-bd65-f927a61c7684}
12412048157aSDexuan Cui  */
12422048157aSDexuan Cui #define HV_KBD_GUID \
12432048157aSDexuan Cui 	.guid = UUID_LE(0xf912ad6d, 0x2b17, 0x48ea, 0xbd, 0x65, \
12442048157aSDexuan Cui 			0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84)
12452048157aSDexuan Cui 
12462048157aSDexuan Cui /*
124796dd86faSK. Y. Srinivasan  * VSS (Backup/Restore) GUID
124896dd86faSK. Y. Srinivasan  */
124996dd86faSK. Y. Srinivasan #define HV_VSS_GUID \
1250af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x35fa2e29, 0xea23, 0x4236, 0x96, 0xae, \
1251af3ff643SK. Y. Srinivasan 			0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40)
125296dd86faSK. Y. Srinivasan /*
125368a2d20bSHaiyang Zhang  * Synthetic Video GUID
125468a2d20bSHaiyang Zhang  * {DA0A7802-E377-4aac-8E77-0558EB1073F8}
125568a2d20bSHaiyang Zhang  */
125668a2d20bSHaiyang Zhang #define HV_SYNTHVID_GUID \
1257af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0xda0a7802, 0xe377, 0x4aac, 0x8e, 0x77, \
1258af3ff643SK. Y. Srinivasan 			0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8)
125968a2d20bSHaiyang Zhang 
126068a2d20bSHaiyang Zhang /*
126198b80d89SK. Y. Srinivasan  * Synthetic FC GUID
126298b80d89SK. Y. Srinivasan  * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda}
126398b80d89SK. Y. Srinivasan  */
126498b80d89SK. Y. Srinivasan #define HV_SYNTHFC_GUID \
1265af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x2f9bcc4a, 0x0069, 0x4af3, 0xb7, 0x6b, \
1266af3ff643SK. Y. Srinivasan 			0x6f, 0xd0, 0xbe, 0x52, 0x8c, 0xda)
126798b80d89SK. Y. Srinivasan 
126898b80d89SK. Y. Srinivasan /*
126901325476SK. Y. Srinivasan  * Guest File Copy Service
127001325476SK. Y. Srinivasan  * {34D14BE3-DEE4-41c8-9AE7-6B174977C192}
127101325476SK. Y. Srinivasan  */
127201325476SK. Y. Srinivasan 
127301325476SK. Y. Srinivasan #define HV_FCOPY_GUID \
1274af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x34d14be3, 0xdee4, 0x41c8, 0x9a, 0xe7, \
1275af3ff643SK. Y. Srinivasan 			0x6b, 0x17, 0x49, 0x77, 0xc1, 0x92)
127601325476SK. Y. Srinivasan 
127701325476SK. Y. Srinivasan /*
127804653a00SK. Y. Srinivasan  * NetworkDirect. This is the guest RDMA service.
127904653a00SK. Y. Srinivasan  * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}
128004653a00SK. Y. Srinivasan  */
128104653a00SK. Y. Srinivasan #define HV_ND_GUID \
1282af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x8c2eaf3d, 0x32a7, 0x4b09, 0xab, 0x99, \
1283af3ff643SK. Y. Srinivasan 			0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01)
128404653a00SK. Y. Srinivasan 
128504653a00SK. Y. Srinivasan /*
12863053c762SJake Oshins  * PCI Express Pass Through
12873053c762SJake Oshins  * {44C4F61D-4444-4400-9D52-802E27EDE19F}
12883053c762SJake Oshins  */
12893053c762SJake Oshins 
12903053c762SJake Oshins #define HV_PCIE_GUID \
1291af3ff643SK. Y. Srinivasan 	.guid = UUID_LE(0x44c4f61d, 0x4444, 0x4400, 0x9d, 0x52, \
1292af3ff643SK. Y. Srinivasan 			0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f)
12933053c762SJake Oshins 
12943053c762SJake Oshins /*
129546a97191SGreg Kroah-Hartman  * Common header for Hyper-V ICs
129646a97191SGreg Kroah-Hartman  */
129746a97191SGreg Kroah-Hartman 
129846a97191SGreg Kroah-Hartman #define ICMSGTYPE_NEGOTIATE		0
129946a97191SGreg Kroah-Hartman #define ICMSGTYPE_HEARTBEAT		1
130046a97191SGreg Kroah-Hartman #define ICMSGTYPE_KVPEXCHANGE		2
130146a97191SGreg Kroah-Hartman #define ICMSGTYPE_SHUTDOWN		3
130246a97191SGreg Kroah-Hartman #define ICMSGTYPE_TIMESYNC		4
130346a97191SGreg Kroah-Hartman #define ICMSGTYPE_VSS			5
130446a97191SGreg Kroah-Hartman 
130546a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_TRANSACTION	1
130646a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_REQUEST		2
130746a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_RESPONSE		4
130846a97191SGreg Kroah-Hartman 
130946a97191SGreg Kroah-Hartman 
131046a97191SGreg Kroah-Hartman /*
131146a97191SGreg Kroah-Hartman  * While we want to handle util services as regular devices,
131246a97191SGreg Kroah-Hartman  * there is only one instance of each of these services; so
131346a97191SGreg Kroah-Hartman  * we statically allocate the service specific state.
131446a97191SGreg Kroah-Hartman  */
131546a97191SGreg Kroah-Hartman 
131646a97191SGreg Kroah-Hartman struct hv_util_service {
131746a97191SGreg Kroah-Hartman 	u8 *recv_buffer;
1318b9830d12SK. Y. Srinivasan 	void *channel;
131946a97191SGreg Kroah-Hartman 	void (*util_cb)(void *);
132046a97191SGreg Kroah-Hartman 	int (*util_init)(struct hv_util_service *);
132146a97191SGreg Kroah-Hartman 	void (*util_deinit)(void);
132246a97191SGreg Kroah-Hartman };
132346a97191SGreg Kroah-Hartman 
132446a97191SGreg Kroah-Hartman struct vmbuspipe_hdr {
132546a97191SGreg Kroah-Hartman 	u32 flags;
132646a97191SGreg Kroah-Hartman 	u32 msgsize;
132746a97191SGreg Kroah-Hartman } __packed;
132846a97191SGreg Kroah-Hartman 
132946a97191SGreg Kroah-Hartman struct ic_version {
133046a97191SGreg Kroah-Hartman 	u16 major;
133146a97191SGreg Kroah-Hartman 	u16 minor;
133246a97191SGreg Kroah-Hartman } __packed;
133346a97191SGreg Kroah-Hartman 
133446a97191SGreg Kroah-Hartman struct icmsg_hdr {
133546a97191SGreg Kroah-Hartman 	struct ic_version icverframe;
133646a97191SGreg Kroah-Hartman 	u16 icmsgtype;
133746a97191SGreg Kroah-Hartman 	struct ic_version icvermsg;
133846a97191SGreg Kroah-Hartman 	u16 icmsgsize;
133946a97191SGreg Kroah-Hartman 	u32 status;
134046a97191SGreg Kroah-Hartman 	u8 ictransaction_id;
134146a97191SGreg Kroah-Hartman 	u8 icflags;
134246a97191SGreg Kroah-Hartman 	u8 reserved[2];
134346a97191SGreg Kroah-Hartman } __packed;
134446a97191SGreg Kroah-Hartman 
134546a97191SGreg Kroah-Hartman struct icmsg_negotiate {
134646a97191SGreg Kroah-Hartman 	u16 icframe_vercnt;
134746a97191SGreg Kroah-Hartman 	u16 icmsg_vercnt;
134846a97191SGreg Kroah-Hartman 	u32 reserved;
134946a97191SGreg Kroah-Hartman 	struct ic_version icversion_data[1]; /* any size array */
135046a97191SGreg Kroah-Hartman } __packed;
135146a97191SGreg Kroah-Hartman 
135246a97191SGreg Kroah-Hartman struct shutdown_msg_data {
135346a97191SGreg Kroah-Hartman 	u32 reason_code;
135446a97191SGreg Kroah-Hartman 	u32 timeout_seconds;
135546a97191SGreg Kroah-Hartman 	u32 flags;
135646a97191SGreg Kroah-Hartman 	u8  display_message[2048];
135746a97191SGreg Kroah-Hartman } __packed;
135846a97191SGreg Kroah-Hartman 
135946a97191SGreg Kroah-Hartman struct heartbeat_msg_data {
136046a97191SGreg Kroah-Hartman 	u64 seq_num;
136146a97191SGreg Kroah-Hartman 	u32 reserved[8];
136246a97191SGreg Kroah-Hartman } __packed;
136346a97191SGreg Kroah-Hartman 
136446a97191SGreg Kroah-Hartman /* Time Sync IC defs */
136546a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_PROBE	0
136646a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_SYNC	1
136746a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_SAMPLE	2
136846a97191SGreg Kroah-Hartman 
136946a97191SGreg Kroah-Hartman #ifdef __x86_64__
137046a97191SGreg Kroah-Hartman #define WLTIMEDELTA	116444736000000000L	/* in 100ns unit */
137146a97191SGreg Kroah-Hartman #else
137246a97191SGreg Kroah-Hartman #define WLTIMEDELTA	116444736000000000LL
137346a97191SGreg Kroah-Hartman #endif
137446a97191SGreg Kroah-Hartman 
137546a97191SGreg Kroah-Hartman struct ictimesync_data {
137646a97191SGreg Kroah-Hartman 	u64 parenttime;
137746a97191SGreg Kroah-Hartman 	u64 childtime;
137846a97191SGreg Kroah-Hartman 	u64 roundtriptime;
137946a97191SGreg Kroah-Hartman 	u8 flags;
138046a97191SGreg Kroah-Hartman } __packed;
138146a97191SGreg Kroah-Hartman 
138246a97191SGreg Kroah-Hartman struct hyperv_service_callback {
138346a97191SGreg Kroah-Hartman 	u8 msg_type;
138446a97191SGreg Kroah-Hartman 	char *log_msg;
138546a97191SGreg Kroah-Hartman 	uuid_le data;
138646a97191SGreg Kroah-Hartman 	struct vmbus_channel *channel;
138746a97191SGreg Kroah-Hartman 	void (*callback) (void *context);
138846a97191SGreg Kroah-Hartman };
138946a97191SGreg Kroah-Hartman 
1390c836d0abSK. Y. Srinivasan #define MAX_SRV_VER	0x7ffffff
13916741335bSK. Y. Srinivasan extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
1392c836d0abSK. Y. Srinivasan 					struct icmsg_negotiate *, u8 *, int,
1393c836d0abSK. Y. Srinivasan 					int);
139446a97191SGreg Kroah-Hartman 
1395638fea33SDexuan Cui void hv_event_tasklet_disable(struct vmbus_channel *channel);
1396638fea33SDexuan Cui void hv_event_tasklet_enable(struct vmbus_channel *channel);
1397638fea33SDexuan Cui 
1398ed6cfcc5SK. Y. Srinivasan void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
139996dd86faSK. Y. Srinivasan 
140037f7278bSK. Y. Srinivasan /*
140137f7278bSK. Y. Srinivasan  * Negotiated version with the Host.
140237f7278bSK. Y. Srinivasan  */
140337f7278bSK. Y. Srinivasan 
140437f7278bSK. Y. Srinivasan extern __u32 vmbus_proto_version;
140537f7278bSK. Y. Srinivasan 
14065c23a1a5SDexuan Cui int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
14075c23a1a5SDexuan Cui 				  const uuid_le *shv_host_servie_id);
14085cc47247SK. Y. Srinivasan void vmbus_set_event(struct vmbus_channel *channel);
1409687f32e6SK. Y. Srinivasan 
1410687f32e6SK. Y. Srinivasan /* Get the start of the ring buffer. */
1411687f32e6SK. Y. Srinivasan static inline void *
1412687f32e6SK. Y. Srinivasan hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
1413687f32e6SK. Y. Srinivasan {
1414687f32e6SK. Y. Srinivasan 	return (void *)ring_info->ring_buffer->buffer;
1415687f32e6SK. Y. Srinivasan }
1416687f32e6SK. Y. Srinivasan 
1417687f32e6SK. Y. Srinivasan /*
1418687f32e6SK. Y. Srinivasan  * To optimize the flow management on the send-side,
1419687f32e6SK. Y. Srinivasan  * when the sender is blocked because of lack of
1420687f32e6SK. Y. Srinivasan  * sufficient space in the ring buffer, potential the
1421687f32e6SK. Y. Srinivasan  * consumer of the ring buffer can signal the producer.
1422687f32e6SK. Y. Srinivasan  * This is controlled by the following parameters:
1423687f32e6SK. Y. Srinivasan  *
1424687f32e6SK. Y. Srinivasan  * 1. pending_send_sz: This is the size in bytes that the
1425687f32e6SK. Y. Srinivasan  *    producer is trying to send.
1426687f32e6SK. Y. Srinivasan  * 2. The feature bit feat_pending_send_sz set to indicate if
1427687f32e6SK. Y. Srinivasan  *    the consumer of the ring will signal when the ring
1428687f32e6SK. Y. Srinivasan  *    state transitions from being full to a state where
1429687f32e6SK. Y. Srinivasan  *    there is room for the producer to send the pending packet.
1430687f32e6SK. Y. Srinivasan  */
1431687f32e6SK. Y. Srinivasan 
1432687f32e6SK. Y. Srinivasan static inline  bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
1433687f32e6SK. Y. Srinivasan {
1434687f32e6SK. Y. Srinivasan 	u32 cur_write_sz;
1435687f32e6SK. Y. Srinivasan 	u32 pending_sz;
1436687f32e6SK. Y. Srinivasan 
1437687f32e6SK. Y. Srinivasan 	/*
1438687f32e6SK. Y. Srinivasan 	 * Issue a full memory barrier before making the signaling decision.
1439687f32e6SK. Y. Srinivasan 	 * Here is the reason for having this barrier:
1440687f32e6SK. Y. Srinivasan 	 * If the reading of the pend_sz (in this function)
1441687f32e6SK. Y. Srinivasan 	 * were to be reordered and read before we commit the new read
1442687f32e6SK. Y. Srinivasan 	 * index (in the calling function)  we could
1443687f32e6SK. Y. Srinivasan 	 * have a problem. If the host were to set the pending_sz after we
1444687f32e6SK. Y. Srinivasan 	 * have sampled pending_sz and go to sleep before we commit the
1445687f32e6SK. Y. Srinivasan 	 * read index, we could miss sending the interrupt. Issue a full
1446687f32e6SK. Y. Srinivasan 	 * memory barrier to address this.
1447687f32e6SK. Y. Srinivasan 	 */
1448687f32e6SK. Y. Srinivasan 	virt_mb();
1449687f32e6SK. Y. Srinivasan 
1450687f32e6SK. Y. Srinivasan 	pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
1451687f32e6SK. Y. Srinivasan 	/* If the other end is not blocked on write don't bother. */
1452687f32e6SK. Y. Srinivasan 	if (pending_sz == 0)
1453687f32e6SK. Y. Srinivasan 		return false;
1454687f32e6SK. Y. Srinivasan 
1455687f32e6SK. Y. Srinivasan 	cur_write_sz = hv_get_bytes_to_write(rbi);
1456687f32e6SK. Y. Srinivasan 
1457687f32e6SK. Y. Srinivasan 	if (cur_write_sz >= pending_sz)
1458687f32e6SK. Y. Srinivasan 		return true;
1459687f32e6SK. Y. Srinivasan 
1460687f32e6SK. Y. Srinivasan 	return false;
1461687f32e6SK. Y. Srinivasan }
1462687f32e6SK. Y. Srinivasan 
1463ab028db4SK. Y. Srinivasan /*
1464ab028db4SK. Y. Srinivasan  * An API to support in-place processing of incoming VMBUS packets.
1465ab028db4SK. Y. Srinivasan  */
1466ab028db4SK. Y. Srinivasan #define VMBUS_PKT_TRAILER	8
1467ab028db4SK. Y. Srinivasan 
1468ab028db4SK. Y. Srinivasan static inline struct vmpacket_descriptor *
1469ab028db4SK. Y. Srinivasan get_next_pkt_raw(struct vmbus_channel *channel)
1470ab028db4SK. Y. Srinivasan {
1471ab028db4SK. Y. Srinivasan 	struct hv_ring_buffer_info *ring_info = &channel->inbound;
1472ab028db4SK. Y. Srinivasan 	u32 read_loc = ring_info->priv_read_index;
1473ab028db4SK. Y. Srinivasan 	void *ring_buffer = hv_get_ring_buffer(ring_info);
1474ab028db4SK. Y. Srinivasan 	struct vmpacket_descriptor *cur_desc;
1475ab028db4SK. Y. Srinivasan 	u32 packetlen;
1476ab028db4SK. Y. Srinivasan 	u32 dsize = ring_info->ring_datasize;
1477ab028db4SK. Y. Srinivasan 	u32 delta = read_loc - ring_info->ring_buffer->read_index;
1478ab028db4SK. Y. Srinivasan 	u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta);
1479ab028db4SK. Y. Srinivasan 
1480ab028db4SK. Y. Srinivasan 	if (bytes_avail_toread < sizeof(struct vmpacket_descriptor))
1481ab028db4SK. Y. Srinivasan 		return NULL;
1482ab028db4SK. Y. Srinivasan 
1483ab028db4SK. Y. Srinivasan 	if ((read_loc + sizeof(*cur_desc)) > dsize)
1484ab028db4SK. Y. Srinivasan 		return NULL;
1485ab028db4SK. Y. Srinivasan 
1486ab028db4SK. Y. Srinivasan 	cur_desc = ring_buffer + read_loc;
1487ab028db4SK. Y. Srinivasan 	packetlen = cur_desc->len8 << 3;
1488ab028db4SK. Y. Srinivasan 
1489ab028db4SK. Y. Srinivasan 	/*
1490ab028db4SK. Y. Srinivasan 	 * If the packet under consideration is wrapping around,
1491ab028db4SK. Y. Srinivasan 	 * return failure.
1492ab028db4SK. Y. Srinivasan 	 */
1493ab028db4SK. Y. Srinivasan 	if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > (dsize - 1))
1494ab028db4SK. Y. Srinivasan 		return NULL;
1495ab028db4SK. Y. Srinivasan 
1496ab028db4SK. Y. Srinivasan 	return cur_desc;
1497ab028db4SK. Y. Srinivasan }
1498ab028db4SK. Y. Srinivasan 
1499ab028db4SK. Y. Srinivasan /*
1500ab028db4SK. Y. Srinivasan  * A helper function to step through packets "in-place"
1501ab028db4SK. Y. Srinivasan  * This API is to be called after each successful call
1502ab028db4SK. Y. Srinivasan  * get_next_pkt_raw().
1503ab028db4SK. Y. Srinivasan  */
1504ab028db4SK. Y. Srinivasan static inline void put_pkt_raw(struct vmbus_channel *channel,
1505ab028db4SK. Y. Srinivasan 				struct vmpacket_descriptor *desc)
1506ab028db4SK. Y. Srinivasan {
1507ab028db4SK. Y. Srinivasan 	struct hv_ring_buffer_info *ring_info = &channel->inbound;
1508ab028db4SK. Y. Srinivasan 	u32 read_loc = ring_info->priv_read_index;
1509ab028db4SK. Y. Srinivasan 	u32 packetlen = desc->len8 << 3;
1510ab028db4SK. Y. Srinivasan 	u32 dsize = ring_info->ring_datasize;
1511ab028db4SK. Y. Srinivasan 
1512ab028db4SK. Y. Srinivasan 	if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > dsize)
1513ab028db4SK. Y. Srinivasan 		BUG();
1514ab028db4SK. Y. Srinivasan 	/*
1515ab028db4SK. Y. Srinivasan 	 * Include the packet trailer.
1516ab028db4SK. Y. Srinivasan 	 */
1517ab028db4SK. Y. Srinivasan 	ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
1518ab028db4SK. Y. Srinivasan }
1519ab028db4SK. Y. Srinivasan 
1520ab028db4SK. Y. Srinivasan /*
1521ab028db4SK. Y. Srinivasan  * This call commits the read index and potentially signals the host.
1522ab028db4SK. Y. Srinivasan  * Here is the pattern for using the "in-place" consumption APIs:
1523ab028db4SK. Y. Srinivasan  *
1524ab028db4SK. Y. Srinivasan  * while (get_next_pkt_raw() {
1525ab028db4SK. Y. Srinivasan  *	process the packet "in-place";
1526ab028db4SK. Y. Srinivasan  *	put_pkt_raw();
1527ab028db4SK. Y. Srinivasan  * }
1528ab028db4SK. Y. Srinivasan  * if (packets processed in place)
1529ab028db4SK. Y. Srinivasan  *	commit_rd_index();
1530ab028db4SK. Y. Srinivasan  */
1531ab028db4SK. Y. Srinivasan static inline void commit_rd_index(struct vmbus_channel *channel)
1532ab028db4SK. Y. Srinivasan {
1533ab028db4SK. Y. Srinivasan 	struct hv_ring_buffer_info *ring_info = &channel->inbound;
1534ab028db4SK. Y. Srinivasan 	/*
1535ab028db4SK. Y. Srinivasan 	 * Make sure all reads are done before we update the read index since
1536ab028db4SK. Y. Srinivasan 	 * the writer may start writing to the read area once the read index
1537ab028db4SK. Y. Srinivasan 	 * is updated.
1538ab028db4SK. Y. Srinivasan 	 */
1539ab028db4SK. Y. Srinivasan 	virt_rmb();
1540ab028db4SK. Y. Srinivasan 	ring_info->ring_buffer->read_index = ring_info->priv_read_index;
1541ab028db4SK. Y. Srinivasan 
1542ab028db4SK. Y. Srinivasan 	if (hv_need_to_signal_on_read(ring_info))
1543ab028db4SK. Y. Srinivasan 		vmbus_set_event(channel);
1544ab028db4SK. Y. Srinivasan }
1545ab028db4SK. Y. Srinivasan 
1546ab028db4SK. Y. Srinivasan 
154746a97191SGreg Kroah-Hartman #endif /* _HYPERV_H */
1548