xref: /linux-6.15/include/linux/hyperv.h (revision 3a28fa35)
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/workqueue.h>
3546a97191SGreg Kroah-Hartman #include <linux/completion.h>
3646a97191SGreg Kroah-Hartman #include <linux/device.h>
3746a97191SGreg Kroah-Hartman #include <linux/mod_devicetable.h>
3846a97191SGreg Kroah-Hartman 
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 
6046a97191SGreg Kroah-Hartman /* 0x18 includes the proprietary packet header */
6146a97191SGreg Kroah-Hartman #define MAX_PAGE_BUFFER_PACKET		(0x18 +			\
6246a97191SGreg Kroah-Hartman 					(sizeof(struct hv_page_buffer) * \
6346a97191SGreg Kroah-Hartman 					 MAX_PAGE_BUFFER_COUNT))
6446a97191SGreg Kroah-Hartman #define MAX_MULTIPAGE_BUFFER_PACKET	(0x18 +			\
6546a97191SGreg Kroah-Hartman 					 sizeof(struct hv_multipage_buffer))
6646a97191SGreg Kroah-Hartman 
6746a97191SGreg Kroah-Hartman 
6846a97191SGreg Kroah-Hartman #pragma pack(pop)
6946a97191SGreg Kroah-Hartman 
7046a97191SGreg Kroah-Hartman struct hv_ring_buffer {
7146a97191SGreg Kroah-Hartman 	/* Offset in bytes from the start of ring data below */
7246a97191SGreg Kroah-Hartman 	u32 write_index;
7346a97191SGreg Kroah-Hartman 
7446a97191SGreg Kroah-Hartman 	/* Offset in bytes from the start of ring data below */
7546a97191SGreg Kroah-Hartman 	u32 read_index;
7646a97191SGreg Kroah-Hartman 
7746a97191SGreg Kroah-Hartman 	u32 interrupt_mask;
7846a97191SGreg Kroah-Hartman 
792416603eSK. Y. Srinivasan 	/*
802416603eSK. Y. Srinivasan 	 * Win8 uses some of the reserved bits to implement
812416603eSK. Y. Srinivasan 	 * interrupt driven flow management. On the send side
822416603eSK. Y. Srinivasan 	 * we can request that the receiver interrupt the sender
832416603eSK. Y. Srinivasan 	 * when the ring transitions from being full to being able
842416603eSK. Y. Srinivasan 	 * to handle a message of size "pending_send_sz".
852416603eSK. Y. Srinivasan 	 *
862416603eSK. Y. Srinivasan 	 * Add necessary state for this enhancement.
8746a97191SGreg Kroah-Hartman 	 */
882416603eSK. Y. Srinivasan 	u32 pending_send_sz;
892416603eSK. Y. Srinivasan 
902416603eSK. Y. Srinivasan 	u32 reserved1[12];
912416603eSK. Y. Srinivasan 
922416603eSK. Y. Srinivasan 	union {
932416603eSK. Y. Srinivasan 		struct {
942416603eSK. Y. Srinivasan 			u32 feat_pending_send_sz:1;
952416603eSK. Y. Srinivasan 		};
962416603eSK. Y. Srinivasan 		u32 value;
972416603eSK. Y. Srinivasan 	} feature_bits;
982416603eSK. Y. Srinivasan 
992416603eSK. Y. Srinivasan 	/* Pad it to PAGE_SIZE so that data starts on page boundary */
1002416603eSK. Y. Srinivasan 	u8	reserved2[4028];
10146a97191SGreg Kroah-Hartman 
10246a97191SGreg Kroah-Hartman 	/*
10346a97191SGreg Kroah-Hartman 	 * Ring data starts here + RingDataStartOffset
10446a97191SGreg Kroah-Hartman 	 * !!! DO NOT place any fields below this !!!
10546a97191SGreg Kroah-Hartman 	 */
10646a97191SGreg Kroah-Hartman 	u8 buffer[0];
10746a97191SGreg Kroah-Hartman } __packed;
10846a97191SGreg Kroah-Hartman 
10946a97191SGreg Kroah-Hartman struct hv_ring_buffer_info {
11046a97191SGreg Kroah-Hartman 	struct hv_ring_buffer *ring_buffer;
11146a97191SGreg Kroah-Hartman 	u32 ring_size;			/* Include the shared header */
11246a97191SGreg Kroah-Hartman 	spinlock_t ring_lock;
11346a97191SGreg Kroah-Hartman 
11446a97191SGreg Kroah-Hartman 	u32 ring_datasize;		/* < ring_size */
11546a97191SGreg Kroah-Hartman 	u32 ring_data_startoffset;
11646a97191SGreg Kroah-Hartman };
11746a97191SGreg Kroah-Hartman 
11833be96e4SHaiyang Zhang /*
11933be96e4SHaiyang Zhang  *
12033be96e4SHaiyang Zhang  * hv_get_ringbuffer_availbytes()
12133be96e4SHaiyang Zhang  *
12233be96e4SHaiyang Zhang  * Get number of bytes available to read and to write to
12333be96e4SHaiyang Zhang  * for the specified ring buffer
12433be96e4SHaiyang Zhang  */
12533be96e4SHaiyang Zhang static inline void
12633be96e4SHaiyang Zhang hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
12733be96e4SHaiyang Zhang 			  u32 *read, u32 *write)
12833be96e4SHaiyang Zhang {
12933be96e4SHaiyang Zhang 	u32 read_loc, write_loc, dsize;
13033be96e4SHaiyang Zhang 
13133be96e4SHaiyang Zhang 	smp_read_barrier_depends();
13233be96e4SHaiyang Zhang 
13333be96e4SHaiyang Zhang 	/* Capture the read/write indices before they changed */
13433be96e4SHaiyang Zhang 	read_loc = rbi->ring_buffer->read_index;
13533be96e4SHaiyang Zhang 	write_loc = rbi->ring_buffer->write_index;
13633be96e4SHaiyang Zhang 	dsize = rbi->ring_datasize;
13733be96e4SHaiyang Zhang 
13833be96e4SHaiyang Zhang 	*write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
13933be96e4SHaiyang Zhang 		read_loc - write_loc;
14033be96e4SHaiyang Zhang 	*read = dsize - *write;
14133be96e4SHaiyang Zhang }
14233be96e4SHaiyang Zhang 
143eafa7072SK. Y. Srinivasan /*
144eafa7072SK. Y. Srinivasan  * VMBUS version is 32 bit entity broken up into
145eafa7072SK. Y. Srinivasan  * two 16 bit quantities: major_number. minor_number.
146eafa7072SK. Y. Srinivasan  *
147eafa7072SK. Y. Srinivasan  * 0 . 13 (Windows Server 2008)
148eafa7072SK. Y. Srinivasan  * 1 . 1  (Windows 7)
149eafa7072SK. Y. Srinivasan  * 2 . 4  (Windows 8)
15003367ef5SK. Y. Srinivasan  * 3 . 0  (Windows 8 R2)
151eafa7072SK. Y. Srinivasan  */
152eafa7072SK. Y. Srinivasan 
153eafa7072SK. Y. Srinivasan #define VERSION_WS2008  ((0 << 16) | (13))
154eafa7072SK. Y. Srinivasan #define VERSION_WIN7    ((1 << 16) | (1))
155eafa7072SK. Y. Srinivasan #define VERSION_WIN8    ((2 << 16) | (4))
15603367ef5SK. Y. Srinivasan #define VERSION_WIN8_1    ((3 << 16) | (0))
157eafa7072SK. Y. Srinivasan 
158eafa7072SK. Y. Srinivasan #define VERSION_INVAL -1
159eafa7072SK. Y. Srinivasan 
16003367ef5SK. Y. Srinivasan #define VERSION_CURRENT VERSION_WIN8_1
16146a97191SGreg Kroah-Hartman 
16246a97191SGreg Kroah-Hartman /* Make maximum size of pipe payload of 16K */
16346a97191SGreg Kroah-Hartman #define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
16446a97191SGreg Kroah-Hartman 
16546a97191SGreg Kroah-Hartman /* Define PipeMode values. */
16646a97191SGreg Kroah-Hartman #define VMBUS_PIPE_TYPE_BYTE		0x00000000
16746a97191SGreg Kroah-Hartman #define VMBUS_PIPE_TYPE_MESSAGE		0x00000004
16846a97191SGreg Kroah-Hartman 
16946a97191SGreg Kroah-Hartman /* The size of the user defined data buffer for non-pipe offers. */
17046a97191SGreg Kroah-Hartman #define MAX_USER_DEFINED_BYTES		120
17146a97191SGreg Kroah-Hartman 
17246a97191SGreg Kroah-Hartman /* The size of the user defined data buffer for pipe offers. */
17346a97191SGreg Kroah-Hartman #define MAX_PIPE_USER_DEFINED_BYTES	116
17446a97191SGreg Kroah-Hartman 
17546a97191SGreg Kroah-Hartman /*
17646a97191SGreg Kroah-Hartman  * At the center of the Channel Management library is the Channel Offer. This
17746a97191SGreg Kroah-Hartman  * struct contains the fundamental information about an offer.
17846a97191SGreg Kroah-Hartman  */
17946a97191SGreg Kroah-Hartman struct vmbus_channel_offer {
18046a97191SGreg Kroah-Hartman 	uuid_le if_type;
18146a97191SGreg Kroah-Hartman 	uuid_le if_instance;
18229423b7eSK. Y. Srinivasan 
18329423b7eSK. Y. Srinivasan 	/*
18429423b7eSK. Y. Srinivasan 	 * These two fields are not currently used.
18529423b7eSK. Y. Srinivasan 	 */
18629423b7eSK. Y. Srinivasan 	u64 reserved1;
18729423b7eSK. Y. Srinivasan 	u64 reserved2;
18829423b7eSK. Y. Srinivasan 
18946a97191SGreg Kroah-Hartman 	u16 chn_flags;
19046a97191SGreg Kroah-Hartman 	u16 mmio_megabytes;		/* in bytes * 1024 * 1024 */
19146a97191SGreg Kroah-Hartman 
19246a97191SGreg Kroah-Hartman 	union {
19346a97191SGreg Kroah-Hartman 		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
19446a97191SGreg Kroah-Hartman 		struct {
19546a97191SGreg Kroah-Hartman 			unsigned char user_def[MAX_USER_DEFINED_BYTES];
19646a97191SGreg Kroah-Hartman 		} std;
19746a97191SGreg Kroah-Hartman 
19846a97191SGreg Kroah-Hartman 		/*
19946a97191SGreg Kroah-Hartman 		 * Pipes:
20046a97191SGreg Kroah-Hartman 		 * The following sructure is an integrated pipe protocol, which
20146a97191SGreg Kroah-Hartman 		 * is implemented on top of standard user-defined data. Pipe
20246a97191SGreg Kroah-Hartman 		 * clients have MAX_PIPE_USER_DEFINED_BYTES left for their own
20346a97191SGreg Kroah-Hartman 		 * use.
20446a97191SGreg Kroah-Hartman 		 */
20546a97191SGreg Kroah-Hartman 		struct {
20646a97191SGreg Kroah-Hartman 			u32  pipe_mode;
20746a97191SGreg Kroah-Hartman 			unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES];
20846a97191SGreg Kroah-Hartman 		} pipe;
20946a97191SGreg Kroah-Hartman 	} u;
21029423b7eSK. Y. Srinivasan 	/*
21129423b7eSK. Y. Srinivasan 	 * The sub_channel_index is defined in win8.
21229423b7eSK. Y. Srinivasan 	 */
21329423b7eSK. Y. Srinivasan 	u16 sub_channel_index;
21429423b7eSK. Y. Srinivasan 	u16 reserved3;
21546a97191SGreg Kroah-Hartman } __packed;
21646a97191SGreg Kroah-Hartman 
21746a97191SGreg Kroah-Hartman /* Server Flags */
21846a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
21946a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES	2
22046a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS		4
22146a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_NAMED_PIPE_MODE			0x10
22246a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_LOOPBACK_OFFER			0x100
22346a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_PARENT_OFFER			0x200
22446a97191SGreg Kroah-Hartman #define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION	0x400
22546a97191SGreg Kroah-Hartman 
22646a97191SGreg Kroah-Hartman struct vmpacket_descriptor {
22746a97191SGreg Kroah-Hartman 	u16 type;
22846a97191SGreg Kroah-Hartman 	u16 offset8;
22946a97191SGreg Kroah-Hartman 	u16 len8;
23046a97191SGreg Kroah-Hartman 	u16 flags;
23146a97191SGreg Kroah-Hartman 	u64 trans_id;
23246a97191SGreg Kroah-Hartman } __packed;
23346a97191SGreg Kroah-Hartman 
23446a97191SGreg Kroah-Hartman struct vmpacket_header {
23546a97191SGreg Kroah-Hartman 	u32 prev_pkt_start_offset;
23646a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor descriptor;
23746a97191SGreg Kroah-Hartman } __packed;
23846a97191SGreg Kroah-Hartman 
23946a97191SGreg Kroah-Hartman struct vmtransfer_page_range {
24046a97191SGreg Kroah-Hartman 	u32 byte_count;
24146a97191SGreg Kroah-Hartman 	u32 byte_offset;
24246a97191SGreg Kroah-Hartman } __packed;
24346a97191SGreg Kroah-Hartman 
24446a97191SGreg Kroah-Hartman struct vmtransfer_page_packet_header {
24546a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
24646a97191SGreg Kroah-Hartman 	u16 xfer_pageset_id;
2471508d811SK. Y. Srinivasan 	u8  sender_owns_set;
24846a97191SGreg Kroah-Hartman 	u8 reserved;
24946a97191SGreg Kroah-Hartman 	u32 range_cnt;
25046a97191SGreg Kroah-Hartman 	struct vmtransfer_page_range ranges[1];
25146a97191SGreg Kroah-Hartman } __packed;
25246a97191SGreg Kroah-Hartman 
25346a97191SGreg Kroah-Hartman struct vmgpadl_packet_header {
25446a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
25546a97191SGreg Kroah-Hartman 	u32 gpadl;
25646a97191SGreg Kroah-Hartman 	u32 reserved;
25746a97191SGreg Kroah-Hartman } __packed;
25846a97191SGreg Kroah-Hartman 
25946a97191SGreg Kroah-Hartman struct vmadd_remove_transfer_page_set {
26046a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
26146a97191SGreg Kroah-Hartman 	u32 gpadl;
26246a97191SGreg Kroah-Hartman 	u16 xfer_pageset_id;
26346a97191SGreg Kroah-Hartman 	u16 reserved;
26446a97191SGreg Kroah-Hartman } __packed;
26546a97191SGreg Kroah-Hartman 
26646a97191SGreg Kroah-Hartman /*
26746a97191SGreg Kroah-Hartman  * This structure defines a range in guest physical space that can be made to
26846a97191SGreg Kroah-Hartman  * look virtually contiguous.
26946a97191SGreg Kroah-Hartman  */
27046a97191SGreg Kroah-Hartman struct gpa_range {
27146a97191SGreg Kroah-Hartman 	u32 byte_count;
27246a97191SGreg Kroah-Hartman 	u32 byte_offset;
27346a97191SGreg Kroah-Hartman 	u64 pfn_array[0];
27446a97191SGreg Kroah-Hartman };
27546a97191SGreg Kroah-Hartman 
27646a97191SGreg Kroah-Hartman /*
27746a97191SGreg Kroah-Hartman  * This is the format for an Establish Gpadl packet, which contains a handle by
27846a97191SGreg Kroah-Hartman  * which this GPADL will be known and a set of GPA ranges associated with it.
27946a97191SGreg Kroah-Hartman  * This can be converted to a MDL by the guest OS.  If there are multiple GPA
28046a97191SGreg Kroah-Hartman  * ranges, then the resulting MDL will be "chained," representing multiple VA
28146a97191SGreg Kroah-Hartman  * ranges.
28246a97191SGreg Kroah-Hartman  */
28346a97191SGreg Kroah-Hartman struct vmestablish_gpadl {
28446a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
28546a97191SGreg Kroah-Hartman 	u32 gpadl;
28646a97191SGreg Kroah-Hartman 	u32 range_cnt;
28746a97191SGreg Kroah-Hartman 	struct gpa_range range[1];
28846a97191SGreg Kroah-Hartman } __packed;
28946a97191SGreg Kroah-Hartman 
29046a97191SGreg Kroah-Hartman /*
29146a97191SGreg Kroah-Hartman  * This is the format for a Teardown Gpadl packet, which indicates that the
29246a97191SGreg Kroah-Hartman  * GPADL handle in the Establish Gpadl packet will never be referenced again.
29346a97191SGreg Kroah-Hartman  */
29446a97191SGreg Kroah-Hartman struct vmteardown_gpadl {
29546a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
29646a97191SGreg Kroah-Hartman 	u32 gpadl;
29746a97191SGreg Kroah-Hartman 	u32 reserved;	/* for alignment to a 8-byte boundary */
29846a97191SGreg Kroah-Hartman } __packed;
29946a97191SGreg Kroah-Hartman 
30046a97191SGreg Kroah-Hartman /*
30146a97191SGreg Kroah-Hartman  * This is the format for a GPA-Direct packet, which contains a set of GPA
30246a97191SGreg Kroah-Hartman  * ranges, in addition to commands and/or data.
30346a97191SGreg Kroah-Hartman  */
30446a97191SGreg Kroah-Hartman struct vmdata_gpa_direct {
30546a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
30646a97191SGreg Kroah-Hartman 	u32 reserved;
30746a97191SGreg Kroah-Hartman 	u32 range_cnt;
30846a97191SGreg Kroah-Hartman 	struct gpa_range range[1];
30946a97191SGreg Kroah-Hartman } __packed;
31046a97191SGreg Kroah-Hartman 
31146a97191SGreg Kroah-Hartman /* This is the format for a Additional Data Packet. */
31246a97191SGreg Kroah-Hartman struct vmadditional_data {
31346a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor d;
31446a97191SGreg Kroah-Hartman 	u64 total_bytes;
31546a97191SGreg Kroah-Hartman 	u32 offset;
31646a97191SGreg Kroah-Hartman 	u32 byte_cnt;
31746a97191SGreg Kroah-Hartman 	unsigned char data[1];
31846a97191SGreg Kroah-Hartman } __packed;
31946a97191SGreg Kroah-Hartman 
32046a97191SGreg Kroah-Hartman union vmpacket_largest_possible_header {
32146a97191SGreg Kroah-Hartman 	struct vmpacket_descriptor simple_hdr;
32246a97191SGreg Kroah-Hartman 	struct vmtransfer_page_packet_header xfer_page_hdr;
32346a97191SGreg Kroah-Hartman 	struct vmgpadl_packet_header gpadl_hdr;
32446a97191SGreg Kroah-Hartman 	struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr;
32546a97191SGreg Kroah-Hartman 	struct vmestablish_gpadl establish_gpadl_hdr;
32646a97191SGreg Kroah-Hartman 	struct vmteardown_gpadl teardown_gpadl_hdr;
32746a97191SGreg Kroah-Hartman 	struct vmdata_gpa_direct data_gpa_direct_hdr;
32846a97191SGreg Kroah-Hartman };
32946a97191SGreg Kroah-Hartman 
33046a97191SGreg Kroah-Hartman #define VMPACKET_DATA_START_ADDRESS(__packet)	\
33146a97191SGreg Kroah-Hartman 	(void *)(((unsigned char *)__packet) +	\
33246a97191SGreg Kroah-Hartman 	 ((struct vmpacket_descriptor)__packet)->offset8 * 8)
33346a97191SGreg Kroah-Hartman 
33446a97191SGreg Kroah-Hartman #define VMPACKET_DATA_LENGTH(__packet)		\
33546a97191SGreg Kroah-Hartman 	((((struct vmpacket_descriptor)__packet)->len8 -	\
33646a97191SGreg Kroah-Hartman 	  ((struct vmpacket_descriptor)__packet)->offset8) * 8)
33746a97191SGreg Kroah-Hartman 
33846a97191SGreg Kroah-Hartman #define VMPACKET_TRANSFER_MODE(__packet)	\
33946a97191SGreg Kroah-Hartman 	(((struct IMPACT)__packet)->type)
34046a97191SGreg Kroah-Hartman 
34146a97191SGreg Kroah-Hartman enum vmbus_packet_type {
34246a97191SGreg Kroah-Hartman 	VM_PKT_INVALID				= 0x0,
34346a97191SGreg Kroah-Hartman 	VM_PKT_SYNCH				= 0x1,
34446a97191SGreg Kroah-Hartman 	VM_PKT_ADD_XFER_PAGESET			= 0x2,
34546a97191SGreg Kroah-Hartman 	VM_PKT_RM_XFER_PAGESET			= 0x3,
34646a97191SGreg Kroah-Hartman 	VM_PKT_ESTABLISH_GPADL			= 0x4,
34746a97191SGreg Kroah-Hartman 	VM_PKT_TEARDOWN_GPADL			= 0x5,
34846a97191SGreg Kroah-Hartman 	VM_PKT_DATA_INBAND			= 0x6,
34946a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_XFER_PAGES		= 0x7,
35046a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_GPADL			= 0x8,
35146a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_GPA_DIRECT		= 0x9,
35246a97191SGreg Kroah-Hartman 	VM_PKT_CANCEL_REQUEST			= 0xa,
35346a97191SGreg Kroah-Hartman 	VM_PKT_COMP				= 0xb,
35446a97191SGreg Kroah-Hartman 	VM_PKT_DATA_USING_ADDITIONAL_PKT	= 0xc,
35546a97191SGreg Kroah-Hartman 	VM_PKT_ADDITIONAL_DATA			= 0xd
35646a97191SGreg Kroah-Hartman };
35746a97191SGreg Kroah-Hartman 
35846a97191SGreg Kroah-Hartman #define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
35946a97191SGreg Kroah-Hartman 
36046a97191SGreg Kroah-Hartman 
36146a97191SGreg Kroah-Hartman /* Version 1 messages */
36246a97191SGreg Kroah-Hartman enum vmbus_channel_message_type {
36346a97191SGreg Kroah-Hartman 	CHANNELMSG_INVALID			=  0,
36446a97191SGreg Kroah-Hartman 	CHANNELMSG_OFFERCHANNEL		=  1,
36546a97191SGreg Kroah-Hartman 	CHANNELMSG_RESCIND_CHANNELOFFER	=  2,
36646a97191SGreg Kroah-Hartman 	CHANNELMSG_REQUESTOFFERS		=  3,
36746a97191SGreg Kroah-Hartman 	CHANNELMSG_ALLOFFERS_DELIVERED	=  4,
36846a97191SGreg Kroah-Hartman 	CHANNELMSG_OPENCHANNEL		=  5,
36946a97191SGreg Kroah-Hartman 	CHANNELMSG_OPENCHANNEL_RESULT		=  6,
37046a97191SGreg Kroah-Hartman 	CHANNELMSG_CLOSECHANNEL		=  7,
37146a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_HEADER		=  8,
37246a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_BODY			=  9,
37346a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_CREATED		= 10,
37446a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_TEARDOWN		= 11,
37546a97191SGreg Kroah-Hartman 	CHANNELMSG_GPADL_TORNDOWN		= 12,
37646a97191SGreg Kroah-Hartman 	CHANNELMSG_RELID_RELEASED		= 13,
37746a97191SGreg Kroah-Hartman 	CHANNELMSG_INITIATE_CONTACT		= 14,
37846a97191SGreg Kroah-Hartman 	CHANNELMSG_VERSION_RESPONSE		= 15,
37946a97191SGreg Kroah-Hartman 	CHANNELMSG_UNLOAD			= 16,
38046a97191SGreg Kroah-Hartman #ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
38146a97191SGreg Kroah-Hartman 	CHANNELMSG_VIEWRANGE_ADD		= 17,
38246a97191SGreg Kroah-Hartman 	CHANNELMSG_VIEWRANGE_REMOVE		= 18,
38346a97191SGreg Kroah-Hartman #endif
38446a97191SGreg Kroah-Hartman 	CHANNELMSG_COUNT
38546a97191SGreg Kroah-Hartman };
38646a97191SGreg Kroah-Hartman 
38746a97191SGreg Kroah-Hartman struct vmbus_channel_message_header {
38846a97191SGreg Kroah-Hartman 	enum vmbus_channel_message_type msgtype;
38946a97191SGreg Kroah-Hartman 	u32 padding;
39046a97191SGreg Kroah-Hartman } __packed;
39146a97191SGreg Kroah-Hartman 
39246a97191SGreg Kroah-Hartman /* Query VMBus Version parameters */
39346a97191SGreg Kroah-Hartman struct vmbus_channel_query_vmbus_version {
39446a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
39546a97191SGreg Kroah-Hartman 	u32 version;
39646a97191SGreg Kroah-Hartman } __packed;
39746a97191SGreg Kroah-Hartman 
39846a97191SGreg Kroah-Hartman /* VMBus Version Supported parameters */
39946a97191SGreg Kroah-Hartman struct vmbus_channel_version_supported {
40046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
4011508d811SK. Y. Srinivasan 	u8 version_supported;
40246a97191SGreg Kroah-Hartman } __packed;
40346a97191SGreg Kroah-Hartman 
40446a97191SGreg Kroah-Hartman /* Offer Channel parameters */
40546a97191SGreg Kroah-Hartman struct vmbus_channel_offer_channel {
40646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
40746a97191SGreg Kroah-Hartman 	struct vmbus_channel_offer offer;
40846a97191SGreg Kroah-Hartman 	u32 child_relid;
40946a97191SGreg Kroah-Hartman 	u8 monitorid;
41029423b7eSK. Y. Srinivasan 	/*
41129423b7eSK. Y. Srinivasan 	 * win7 and beyond splits this field into a bit field.
41229423b7eSK. Y. Srinivasan 	 */
41329423b7eSK. Y. Srinivasan 	u8 monitor_allocated:1;
41429423b7eSK. Y. Srinivasan 	u8 reserved:7;
41529423b7eSK. Y. Srinivasan 	/*
41629423b7eSK. Y. Srinivasan 	 * These are new fields added in win7 and later.
41729423b7eSK. Y. Srinivasan 	 * Do not access these fields without checking the
41829423b7eSK. Y. Srinivasan 	 * negotiated protocol.
41929423b7eSK. Y. Srinivasan 	 *
42029423b7eSK. Y. Srinivasan 	 * If "is_dedicated_interrupt" is set, we must not set the
42129423b7eSK. Y. Srinivasan 	 * associated bit in the channel bitmap while sending the
42229423b7eSK. Y. Srinivasan 	 * interrupt to the host.
42329423b7eSK. Y. Srinivasan 	 *
42429423b7eSK. Y. Srinivasan 	 * connection_id is to be used in signaling the host.
42529423b7eSK. Y. Srinivasan 	 */
42629423b7eSK. Y. Srinivasan 	u16 is_dedicated_interrupt:1;
42729423b7eSK. Y. Srinivasan 	u16 reserved1:15;
42829423b7eSK. Y. Srinivasan 	u32 connection_id;
42946a97191SGreg Kroah-Hartman } __packed;
43046a97191SGreg Kroah-Hartman 
43146a97191SGreg Kroah-Hartman /* Rescind Offer parameters */
43246a97191SGreg Kroah-Hartman struct vmbus_channel_rescind_offer {
43346a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
43446a97191SGreg Kroah-Hartman 	u32 child_relid;
43546a97191SGreg Kroah-Hartman } __packed;
43646a97191SGreg Kroah-Hartman 
43746a97191SGreg Kroah-Hartman /*
43846a97191SGreg Kroah-Hartman  * Request Offer -- no parameters, SynIC message contains the partition ID
43946a97191SGreg Kroah-Hartman  * Set Snoop -- no parameters, SynIC message contains the partition ID
44046a97191SGreg Kroah-Hartman  * Clear Snoop -- no parameters, SynIC message contains the partition ID
44146a97191SGreg Kroah-Hartman  * All Offers Delivered -- no parameters, SynIC message contains the partition
44246a97191SGreg Kroah-Hartman  *		           ID
44346a97191SGreg Kroah-Hartman  * Flush Client -- no parameters, SynIC message contains the partition ID
44446a97191SGreg Kroah-Hartman  */
44546a97191SGreg Kroah-Hartman 
44646a97191SGreg Kroah-Hartman /* Open Channel parameters */
44746a97191SGreg Kroah-Hartman struct vmbus_channel_open_channel {
44846a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
44946a97191SGreg Kroah-Hartman 
45046a97191SGreg Kroah-Hartman 	/* Identifies the specific VMBus channel that is being opened. */
45146a97191SGreg Kroah-Hartman 	u32 child_relid;
45246a97191SGreg Kroah-Hartman 
45346a97191SGreg Kroah-Hartman 	/* ID making a particular open request at a channel offer unique. */
45446a97191SGreg Kroah-Hartman 	u32 openid;
45546a97191SGreg Kroah-Hartman 
45646a97191SGreg Kroah-Hartman 	/* GPADL for the channel's ring buffer. */
45746a97191SGreg Kroah-Hartman 	u32 ringbuffer_gpadlhandle;
45846a97191SGreg Kroah-Hartman 
459abbf3b2aSK. Y. Srinivasan 	/*
460abbf3b2aSK. Y. Srinivasan 	 * Starting with win8, this field will be used to specify
461abbf3b2aSK. Y. Srinivasan 	 * the target virtual processor on which to deliver the interrupt for
462abbf3b2aSK. Y. Srinivasan 	 * the host to guest communication.
463abbf3b2aSK. Y. Srinivasan 	 * Prior to win8, incoming channel interrupts would only
464abbf3b2aSK. Y. Srinivasan 	 * be delivered on cpu 0. Setting this value to 0 would
465abbf3b2aSK. Y. Srinivasan 	 * preserve the earlier behavior.
466abbf3b2aSK. Y. Srinivasan 	 */
467abbf3b2aSK. Y. Srinivasan 	u32 target_vp;
46846a97191SGreg Kroah-Hartman 
46946a97191SGreg Kroah-Hartman 	/*
47046a97191SGreg Kroah-Hartman 	* The upstream ring buffer begins at offset zero in the memory
47146a97191SGreg Kroah-Hartman 	* described by RingBufferGpadlHandle. The downstream ring buffer
47246a97191SGreg Kroah-Hartman 	* follows it at this offset (in pages).
47346a97191SGreg Kroah-Hartman 	*/
47446a97191SGreg Kroah-Hartman 	u32 downstream_ringbuffer_pageoffset;
47546a97191SGreg Kroah-Hartman 
47646a97191SGreg Kroah-Hartman 	/* User-specific data to be passed along to the server endpoint. */
47746a97191SGreg Kroah-Hartman 	unsigned char userdata[MAX_USER_DEFINED_BYTES];
47846a97191SGreg Kroah-Hartman } __packed;
47946a97191SGreg Kroah-Hartman 
48046a97191SGreg Kroah-Hartman /* Open Channel Result parameters */
48146a97191SGreg Kroah-Hartman struct vmbus_channel_open_result {
48246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
48346a97191SGreg Kroah-Hartman 	u32 child_relid;
48446a97191SGreg Kroah-Hartman 	u32 openid;
48546a97191SGreg Kroah-Hartman 	u32 status;
48646a97191SGreg Kroah-Hartman } __packed;
48746a97191SGreg Kroah-Hartman 
48846a97191SGreg Kroah-Hartman /* Close channel parameters; */
48946a97191SGreg Kroah-Hartman struct vmbus_channel_close_channel {
49046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
49146a97191SGreg Kroah-Hartman 	u32 child_relid;
49246a97191SGreg Kroah-Hartman } __packed;
49346a97191SGreg Kroah-Hartman 
49446a97191SGreg Kroah-Hartman /* Channel Message GPADL */
49546a97191SGreg Kroah-Hartman #define GPADL_TYPE_RING_BUFFER		1
49646a97191SGreg Kroah-Hartman #define GPADL_TYPE_SERVER_SAVE_AREA	2
49746a97191SGreg Kroah-Hartman #define GPADL_TYPE_TRANSACTION		8
49846a97191SGreg Kroah-Hartman 
49946a97191SGreg Kroah-Hartman /*
50046a97191SGreg Kroah-Hartman  * The number of PFNs in a GPADL message is defined by the number of
50146a97191SGreg Kroah-Hartman  * pages that would be spanned by ByteCount and ByteOffset.  If the
50246a97191SGreg Kroah-Hartman  * implied number of PFNs won't fit in this packet, there will be a
50346a97191SGreg Kroah-Hartman  * follow-up packet that contains more.
50446a97191SGreg Kroah-Hartman  */
50546a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_header {
50646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
50746a97191SGreg Kroah-Hartman 	u32 child_relid;
50846a97191SGreg Kroah-Hartman 	u32 gpadl;
50946a97191SGreg Kroah-Hartman 	u16 range_buflen;
51046a97191SGreg Kroah-Hartman 	u16 rangecount;
51146a97191SGreg Kroah-Hartman 	struct gpa_range range[0];
51246a97191SGreg Kroah-Hartman } __packed;
51346a97191SGreg Kroah-Hartman 
51446a97191SGreg Kroah-Hartman /* This is the followup packet that contains more PFNs. */
51546a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_body {
51646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
51746a97191SGreg Kroah-Hartman 	u32 msgnumber;
51846a97191SGreg Kroah-Hartman 	u32 gpadl;
51946a97191SGreg Kroah-Hartman 	u64 pfn[0];
52046a97191SGreg Kroah-Hartman } __packed;
52146a97191SGreg Kroah-Hartman 
52246a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_created {
52346a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
52446a97191SGreg Kroah-Hartman 	u32 child_relid;
52546a97191SGreg Kroah-Hartman 	u32 gpadl;
52646a97191SGreg Kroah-Hartman 	u32 creation_status;
52746a97191SGreg Kroah-Hartman } __packed;
52846a97191SGreg Kroah-Hartman 
52946a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_teardown {
53046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
53146a97191SGreg Kroah-Hartman 	u32 child_relid;
53246a97191SGreg Kroah-Hartman 	u32 gpadl;
53346a97191SGreg Kroah-Hartman } __packed;
53446a97191SGreg Kroah-Hartman 
53546a97191SGreg Kroah-Hartman struct vmbus_channel_gpadl_torndown {
53646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
53746a97191SGreg Kroah-Hartman 	u32 gpadl;
53846a97191SGreg Kroah-Hartman } __packed;
53946a97191SGreg Kroah-Hartman 
54046a97191SGreg Kroah-Hartman #ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
54146a97191SGreg Kroah-Hartman struct vmbus_channel_view_range_add {
54246a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
54346a97191SGreg Kroah-Hartman 	PHYSICAL_ADDRESS viewrange_base;
54446a97191SGreg Kroah-Hartman 	u64 viewrange_length;
54546a97191SGreg Kroah-Hartman 	u32 child_relid;
54646a97191SGreg Kroah-Hartman } __packed;
54746a97191SGreg Kroah-Hartman 
54846a97191SGreg Kroah-Hartman struct vmbus_channel_view_range_remove {
54946a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
55046a97191SGreg Kroah-Hartman 	PHYSICAL_ADDRESS viewrange_base;
55146a97191SGreg Kroah-Hartman 	u32 child_relid;
55246a97191SGreg Kroah-Hartman } __packed;
55346a97191SGreg Kroah-Hartman #endif
55446a97191SGreg Kroah-Hartman 
55546a97191SGreg Kroah-Hartman struct vmbus_channel_relid_released {
55646a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
55746a97191SGreg Kroah-Hartman 	u32 child_relid;
55846a97191SGreg Kroah-Hartman } __packed;
55946a97191SGreg Kroah-Hartman 
56046a97191SGreg Kroah-Hartman struct vmbus_channel_initiate_contact {
56146a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
56246a97191SGreg Kroah-Hartman 	u32 vmbus_version_requested;
563e28bab48SK. Y. Srinivasan 	u32 target_vcpu; /* The VCPU the host should respond to */
56446a97191SGreg Kroah-Hartman 	u64 interrupt_page;
56546a97191SGreg Kroah-Hartman 	u64 monitor_page1;
56646a97191SGreg Kroah-Hartman 	u64 monitor_page2;
56746a97191SGreg Kroah-Hartman } __packed;
56846a97191SGreg Kroah-Hartman 
56946a97191SGreg Kroah-Hartman struct vmbus_channel_version_response {
57046a97191SGreg Kroah-Hartman 	struct vmbus_channel_message_header header;
5711508d811SK. Y. Srinivasan 	u8 version_supported;
57246a97191SGreg Kroah-Hartman } __packed;
57346a97191SGreg Kroah-Hartman 
57446a97191SGreg Kroah-Hartman enum vmbus_channel_state {
57546a97191SGreg Kroah-Hartman 	CHANNEL_OFFER_STATE,
57646a97191SGreg Kroah-Hartman 	CHANNEL_OPENING_STATE,
57746a97191SGreg Kroah-Hartman 	CHANNEL_OPEN_STATE,
578e68d2971SK. Y. Srinivasan 	CHANNEL_OPENED_STATE,
57946a97191SGreg Kroah-Hartman };
58046a97191SGreg Kroah-Hartman 
58146a97191SGreg Kroah-Hartman /*
58246a97191SGreg Kroah-Hartman  * Represents each channel msg on the vmbus connection This is a
58346a97191SGreg Kroah-Hartman  * variable-size data structure depending on the msg type itself
58446a97191SGreg Kroah-Hartman  */
58546a97191SGreg Kroah-Hartman struct vmbus_channel_msginfo {
58646a97191SGreg Kroah-Hartman 	/* Bookkeeping stuff */
58746a97191SGreg Kroah-Hartman 	struct list_head msglistentry;
58846a97191SGreg Kroah-Hartman 
58946a97191SGreg Kroah-Hartman 	/* So far, this is only used to handle gpadl body message */
59046a97191SGreg Kroah-Hartman 	struct list_head submsglist;
59146a97191SGreg Kroah-Hartman 
59246a97191SGreg Kroah-Hartman 	/* Synchronize the request/response if needed */
59346a97191SGreg Kroah-Hartman 	struct completion  waitevent;
59446a97191SGreg Kroah-Hartman 	union {
59546a97191SGreg Kroah-Hartman 		struct vmbus_channel_version_supported version_supported;
59646a97191SGreg Kroah-Hartman 		struct vmbus_channel_open_result open_result;
59746a97191SGreg Kroah-Hartman 		struct vmbus_channel_gpadl_torndown gpadl_torndown;
59846a97191SGreg Kroah-Hartman 		struct vmbus_channel_gpadl_created gpadl_created;
59946a97191SGreg Kroah-Hartman 		struct vmbus_channel_version_response version_response;
60046a97191SGreg Kroah-Hartman 	} response;
60146a97191SGreg Kroah-Hartman 
60246a97191SGreg Kroah-Hartman 	u32 msgsize;
60346a97191SGreg Kroah-Hartman 	/*
60446a97191SGreg Kroah-Hartman 	 * The channel message that goes out on the "wire".
60546a97191SGreg Kroah-Hartman 	 * It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header
60646a97191SGreg Kroah-Hartman 	 */
60746a97191SGreg Kroah-Hartman 	unsigned char msg[0];
60846a97191SGreg Kroah-Hartman };
60946a97191SGreg Kroah-Hartman 
61046a97191SGreg Kroah-Hartman struct vmbus_close_msg {
61146a97191SGreg Kroah-Hartman 	struct vmbus_channel_msginfo info;
61246a97191SGreg Kroah-Hartman 	struct vmbus_channel_close_channel msg;
61346a97191SGreg Kroah-Hartman };
61446a97191SGreg Kroah-Hartman 
615b3bf60c7SK. Y. Srinivasan /* Define connection identifier type. */
616b3bf60c7SK. Y. Srinivasan union hv_connection_id {
617b3bf60c7SK. Y. Srinivasan 	u32 asu32;
618b3bf60c7SK. Y. Srinivasan 	struct {
619b3bf60c7SK. Y. Srinivasan 		u32 id:24;
620b3bf60c7SK. Y. Srinivasan 		u32 reserved:8;
621b3bf60c7SK. Y. Srinivasan 	} u;
622b3bf60c7SK. Y. Srinivasan };
623b3bf60c7SK. Y. Srinivasan 
624b3bf60c7SK. Y. Srinivasan /* Definition of the hv_signal_event hypercall input structure. */
625b3bf60c7SK. Y. Srinivasan struct hv_input_signal_event {
626b3bf60c7SK. Y. Srinivasan 	union hv_connection_id connectionid;
627b3bf60c7SK. Y. Srinivasan 	u16 flag_number;
628b3bf60c7SK. Y. Srinivasan 	u16 rsvdz;
629b3bf60c7SK. Y. Srinivasan };
630b3bf60c7SK. Y. Srinivasan 
631b3bf60c7SK. Y. Srinivasan struct hv_input_signal_event_buffer {
632b3bf60c7SK. Y. Srinivasan 	u64 align8;
633b3bf60c7SK. Y. Srinivasan 	struct hv_input_signal_event event;
634b3bf60c7SK. Y. Srinivasan };
635b3bf60c7SK. Y. Srinivasan 
63646a97191SGreg Kroah-Hartman struct vmbus_channel {
63746a97191SGreg Kroah-Hartman 	struct list_head listentry;
63846a97191SGreg Kroah-Hartman 
63946a97191SGreg Kroah-Hartman 	struct hv_device *device_obj;
64046a97191SGreg Kroah-Hartman 
64146a97191SGreg Kroah-Hartman 	struct work_struct work;
64246a97191SGreg Kroah-Hartman 
64346a97191SGreg Kroah-Hartman 	enum vmbus_channel_state state;
64446a97191SGreg Kroah-Hartman 
64546a97191SGreg Kroah-Hartman 	struct vmbus_channel_offer_channel offermsg;
64646a97191SGreg Kroah-Hartman 	/*
64746a97191SGreg Kroah-Hartman 	 * These are based on the OfferMsg.MonitorId.
64846a97191SGreg Kroah-Hartman 	 * Save it here for easy access.
64946a97191SGreg Kroah-Hartman 	 */
65046a97191SGreg Kroah-Hartman 	u8 monitor_grp;
65146a97191SGreg Kroah-Hartman 	u8 monitor_bit;
65246a97191SGreg Kroah-Hartman 
65346a97191SGreg Kroah-Hartman 	u32 ringbuffer_gpadlhandle;
65446a97191SGreg Kroah-Hartman 
65546a97191SGreg Kroah-Hartman 	/* Allocated memory for ring buffer */
65646a97191SGreg Kroah-Hartman 	void *ringbuffer_pages;
65746a97191SGreg Kroah-Hartman 	u32 ringbuffer_pagecount;
65846a97191SGreg Kroah-Hartman 	struct hv_ring_buffer_info outbound;	/* send to parent */
65946a97191SGreg Kroah-Hartman 	struct hv_ring_buffer_info inbound;	/* receive from parent */
66046a97191SGreg Kroah-Hartman 	spinlock_t inbound_lock;
66146a97191SGreg Kroah-Hartman 	struct workqueue_struct *controlwq;
66246a97191SGreg Kroah-Hartman 
66346a97191SGreg Kroah-Hartman 	struct vmbus_close_msg close_msg;
66446a97191SGreg Kroah-Hartman 
66546a97191SGreg Kroah-Hartman 	/* Channel callback are invoked in this workqueue context */
66646a97191SGreg Kroah-Hartman 	/* HANDLE dataWorkQueue; */
66746a97191SGreg Kroah-Hartman 
66846a97191SGreg Kroah-Hartman 	void (*onchannel_callback)(void *context);
66946a97191SGreg Kroah-Hartman 	void *channel_callback_context;
670132368bdSK. Y. Srinivasan 
671132368bdSK. Y. Srinivasan 	/*
672132368bdSK. Y. Srinivasan 	 * A channel can be marked for efficient (batched)
673132368bdSK. Y. Srinivasan 	 * reading:
674132368bdSK. Y. Srinivasan 	 * If batched_reading is set to "true", we read until the
675132368bdSK. Y. Srinivasan 	 * channel is empty and hold off interrupts from the host
676132368bdSK. Y. Srinivasan 	 * during the entire read process.
677132368bdSK. Y. Srinivasan 	 * If batched_reading is set to "false", the client is not
678132368bdSK. Y. Srinivasan 	 * going to perform batched reading.
679132368bdSK. Y. Srinivasan 	 *
680132368bdSK. Y. Srinivasan 	 * By default we will enable batched reading; specific
681132368bdSK. Y. Srinivasan 	 * drivers that don't want this behavior can turn it off.
682132368bdSK. Y. Srinivasan 	 */
683132368bdSK. Y. Srinivasan 
684132368bdSK. Y. Srinivasan 	bool batched_reading;
685b3bf60c7SK. Y. Srinivasan 
686b3bf60c7SK. Y. Srinivasan 	bool is_dedicated_interrupt;
687b3bf60c7SK. Y. Srinivasan 	struct hv_input_signal_event_buffer sig_buf;
688b3bf60c7SK. Y. Srinivasan 	struct hv_input_signal_event *sig_event;
689abbf3b2aSK. Y. Srinivasan 
690abbf3b2aSK. Y. Srinivasan 	/*
691abbf3b2aSK. Y. Srinivasan 	 * Starting with win8, this field will be used to specify
692abbf3b2aSK. Y. Srinivasan 	 * the target virtual processor on which to deliver the interrupt for
693abbf3b2aSK. Y. Srinivasan 	 * the host to guest communication.
694abbf3b2aSK. Y. Srinivasan 	 * Prior to win8, incoming channel interrupts would only
695abbf3b2aSK. Y. Srinivasan 	 * be delivered on cpu 0. Setting this value to 0 would
696abbf3b2aSK. Y. Srinivasan 	 * preserve the earlier behavior.
697abbf3b2aSK. Y. Srinivasan 	 */
698abbf3b2aSK. Y. Srinivasan 	u32 target_vp;
699d3ba720dSK. Y. Srinivasan 	/* The corresponding CPUID in the guest */
700d3ba720dSK. Y. Srinivasan 	u32 target_cpu;
701e68d2971SK. Y. Srinivasan 	/*
702e68d2971SK. Y. Srinivasan 	 * Support for sub-channels. For high performance devices,
703e68d2971SK. Y. Srinivasan 	 * it will be useful to have multiple sub-channels to support
704e68d2971SK. Y. Srinivasan 	 * a scalable communication infrastructure with the host.
705e68d2971SK. Y. Srinivasan 	 * The support for sub-channels is implemented as an extention
706e68d2971SK. Y. Srinivasan 	 * to the current infrastructure.
707e68d2971SK. Y. Srinivasan 	 * The initial offer is considered the primary channel and this
708e68d2971SK. Y. Srinivasan 	 * offer message will indicate if the host supports sub-channels.
709e68d2971SK. Y. Srinivasan 	 * The guest is free to ask for sub-channels to be offerred and can
710e68d2971SK. Y. Srinivasan 	 * open these sub-channels as a normal "primary" channel. However,
711e68d2971SK. Y. Srinivasan 	 * all sub-channels will have the same type and instance guids as the
712e68d2971SK. Y. Srinivasan 	 * primary channel. Requests sent on a given channel will result in a
713e68d2971SK. Y. Srinivasan 	 * response on the same channel.
714e68d2971SK. Y. Srinivasan 	 */
715e68d2971SK. Y. Srinivasan 
716e68d2971SK. Y. Srinivasan 	/*
717e68d2971SK. Y. Srinivasan 	 * Sub-channel creation callback. This callback will be called in
718e68d2971SK. Y. Srinivasan 	 * process context when a sub-channel offer is received from the host.
719e68d2971SK. Y. Srinivasan 	 * The guest can open the sub-channel in the context of this callback.
720e68d2971SK. Y. Srinivasan 	 */
721e68d2971SK. Y. Srinivasan 	void (*sc_creation_callback)(struct vmbus_channel *new_sc);
722e68d2971SK. Y. Srinivasan 
723e68d2971SK. Y. Srinivasan 	spinlock_t sc_lock;
724e68d2971SK. Y. Srinivasan 	/*
725e68d2971SK. Y. Srinivasan 	 * All Sub-channels of a primary channel are linked here.
726e68d2971SK. Y. Srinivasan 	 */
727e68d2971SK. Y. Srinivasan 	struct list_head sc_list;
728e68d2971SK. Y. Srinivasan 	/*
729e68d2971SK. Y. Srinivasan 	 * The primary channel this sub-channel belongs to.
730e68d2971SK. Y. Srinivasan 	 * This will be NULL for the primary channel.
731e68d2971SK. Y. Srinivasan 	 */
732e68d2971SK. Y. Srinivasan 	struct vmbus_channel *primary_channel;
7338a7206a8SK. Y. Srinivasan 	/*
7348a7206a8SK. Y. Srinivasan 	 * Support per-channel state for use by vmbus drivers.
7358a7206a8SK. Y. Srinivasan 	 */
7368a7206a8SK. Y. Srinivasan 	void *per_channel_state;
737*3a28fa35SK. Y. Srinivasan 	/*
738*3a28fa35SK. Y. Srinivasan 	 * To support per-cpu lookup mapping of relid to channel,
739*3a28fa35SK. Y. Srinivasan 	 * link up channels based on their CPU affinity.
740*3a28fa35SK. Y. Srinivasan 	 */
741*3a28fa35SK. Y. Srinivasan 	struct list_head percpu_list;
74246a97191SGreg Kroah-Hartman };
74346a97191SGreg Kroah-Hartman 
744132368bdSK. Y. Srinivasan static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
745132368bdSK. Y. Srinivasan {
746132368bdSK. Y. Srinivasan 	c->batched_reading = state;
747132368bdSK. Y. Srinivasan }
748132368bdSK. Y. Srinivasan 
7498a7206a8SK. Y. Srinivasan static inline void set_per_channel_state(struct vmbus_channel *c, void *s)
7508a7206a8SK. Y. Srinivasan {
7518a7206a8SK. Y. Srinivasan 	c->per_channel_state = s;
7528a7206a8SK. Y. Srinivasan }
7538a7206a8SK. Y. Srinivasan 
7548a7206a8SK. Y. Srinivasan static inline void *get_per_channel_state(struct vmbus_channel *c)
7558a7206a8SK. Y. Srinivasan {
7568a7206a8SK. Y. Srinivasan 	return c->per_channel_state;
7578a7206a8SK. Y. Srinivasan }
7588a7206a8SK. Y. Srinivasan 
75946a97191SGreg Kroah-Hartman void vmbus_onmessage(void *context);
76046a97191SGreg Kroah-Hartman 
76146a97191SGreg Kroah-Hartman int vmbus_request_offers(void);
76246a97191SGreg Kroah-Hartman 
763e68d2971SK. Y. Srinivasan /*
764e68d2971SK. Y. Srinivasan  * APIs for managing sub-channels.
765e68d2971SK. Y. Srinivasan  */
766e68d2971SK. Y. Srinivasan 
767e68d2971SK. Y. Srinivasan void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
768e68d2971SK. Y. Srinivasan 			void (*sc_cr_cb)(struct vmbus_channel *new_sc));
769e68d2971SK. Y. Srinivasan 
770e68d2971SK. Y. Srinivasan /*
771e68d2971SK. Y. Srinivasan  * Retrieve the (sub) channel on which to send an outgoing request.
772e68d2971SK. Y. Srinivasan  * When a primary channel has multiple sub-channels, we choose a
773e68d2971SK. Y. Srinivasan  * channel whose VCPU binding is closest to the VCPU on which
774e68d2971SK. Y. Srinivasan  * this call is being made.
775e68d2971SK. Y. Srinivasan  */
776e68d2971SK. Y. Srinivasan struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary);
777e68d2971SK. Y. Srinivasan 
778e68d2971SK. Y. Srinivasan /*
779e68d2971SK. Y. Srinivasan  * Check if sub-channels have already been offerred. This API will be useful
780e68d2971SK. Y. Srinivasan  * when the driver is unloaded after establishing sub-channels. In this case,
781e68d2971SK. Y. Srinivasan  * when the driver is re-loaded, the driver would have to check if the
782e68d2971SK. Y. Srinivasan  * subchannels have already been established before attempting to request
783e68d2971SK. Y. Srinivasan  * the creation of sub-channels.
784e68d2971SK. Y. Srinivasan  * This function returns TRUE to indicate that subchannels have already been
785e68d2971SK. Y. Srinivasan  * created.
786e68d2971SK. Y. Srinivasan  * This function should be invoked after setting the callback function for
787e68d2971SK. Y. Srinivasan  * sub-channel creation.
788e68d2971SK. Y. Srinivasan  */
789e68d2971SK. Y. Srinivasan bool vmbus_are_subchannels_present(struct vmbus_channel *primary);
790e68d2971SK. Y. Srinivasan 
79146a97191SGreg Kroah-Hartman /* The format must be the same as struct vmdata_gpa_direct */
79246a97191SGreg Kroah-Hartman struct vmbus_channel_packet_page_buffer {
79346a97191SGreg Kroah-Hartman 	u16 type;
79446a97191SGreg Kroah-Hartman 	u16 dataoffset8;
79546a97191SGreg Kroah-Hartman 	u16 length8;
79646a97191SGreg Kroah-Hartman 	u16 flags;
79746a97191SGreg Kroah-Hartman 	u64 transactionid;
79846a97191SGreg Kroah-Hartman 	u32 reserved;
79946a97191SGreg Kroah-Hartman 	u32 rangecount;
80046a97191SGreg Kroah-Hartman 	struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT];
80146a97191SGreg Kroah-Hartman } __packed;
80246a97191SGreg Kroah-Hartman 
80346a97191SGreg Kroah-Hartman /* The format must be the same as struct vmdata_gpa_direct */
80446a97191SGreg Kroah-Hartman struct vmbus_channel_packet_multipage_buffer {
80546a97191SGreg Kroah-Hartman 	u16 type;
80646a97191SGreg Kroah-Hartman 	u16 dataoffset8;
80746a97191SGreg Kroah-Hartman 	u16 length8;
80846a97191SGreg Kroah-Hartman 	u16 flags;
80946a97191SGreg Kroah-Hartman 	u64 transactionid;
81046a97191SGreg Kroah-Hartman 	u32 reserved;
81146a97191SGreg Kroah-Hartman 	u32 rangecount;		/* Always 1 in this case */
81246a97191SGreg Kroah-Hartman 	struct hv_multipage_buffer range;
81346a97191SGreg Kroah-Hartman } __packed;
81446a97191SGreg Kroah-Hartman 
81546a97191SGreg Kroah-Hartman 
81646a97191SGreg Kroah-Hartman extern int vmbus_open(struct vmbus_channel *channel,
81746a97191SGreg Kroah-Hartman 			    u32 send_ringbuffersize,
81846a97191SGreg Kroah-Hartman 			    u32 recv_ringbuffersize,
81946a97191SGreg Kroah-Hartman 			    void *userdata,
82046a97191SGreg Kroah-Hartman 			    u32 userdatalen,
82146a97191SGreg Kroah-Hartman 			    void(*onchannel_callback)(void *context),
82246a97191SGreg Kroah-Hartman 			    void *context);
82346a97191SGreg Kroah-Hartman 
82446a97191SGreg Kroah-Hartman extern void vmbus_close(struct vmbus_channel *channel);
82546a97191SGreg Kroah-Hartman 
82646a97191SGreg Kroah-Hartman extern int vmbus_sendpacket(struct vmbus_channel *channel,
827011a7c3cSK. Y. Srinivasan 				  void *buffer,
82846a97191SGreg Kroah-Hartman 				  u32 bufferLen,
82946a97191SGreg Kroah-Hartman 				  u64 requestid,
83046a97191SGreg Kroah-Hartman 				  enum vmbus_packet_type type,
83146a97191SGreg Kroah-Hartman 				  u32 flags);
83246a97191SGreg Kroah-Hartman 
83346a97191SGreg Kroah-Hartman extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
83446a97191SGreg Kroah-Hartman 					    struct hv_page_buffer pagebuffers[],
83546a97191SGreg Kroah-Hartman 					    u32 pagecount,
83646a97191SGreg Kroah-Hartman 					    void *buffer,
83746a97191SGreg Kroah-Hartman 					    u32 bufferlen,
83846a97191SGreg Kroah-Hartman 					    u64 requestid);
83946a97191SGreg Kroah-Hartman 
84046a97191SGreg Kroah-Hartman extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
84146a97191SGreg Kroah-Hartman 					struct hv_multipage_buffer *mpb,
84246a97191SGreg Kroah-Hartman 					void *buffer,
84346a97191SGreg Kroah-Hartman 					u32 bufferlen,
84446a97191SGreg Kroah-Hartman 					u64 requestid);
84546a97191SGreg Kroah-Hartman 
84646a97191SGreg Kroah-Hartman extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
84746a97191SGreg Kroah-Hartman 				      void *kbuffer,
84846a97191SGreg Kroah-Hartman 				      u32 size,
84946a97191SGreg Kroah-Hartman 				      u32 *gpadl_handle);
85046a97191SGreg Kroah-Hartman 
85146a97191SGreg Kroah-Hartman extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
85246a97191SGreg Kroah-Hartman 				     u32 gpadl_handle);
85346a97191SGreg Kroah-Hartman 
85446a97191SGreg Kroah-Hartman extern int vmbus_recvpacket(struct vmbus_channel *channel,
85546a97191SGreg Kroah-Hartman 				  void *buffer,
85646a97191SGreg Kroah-Hartman 				  u32 bufferlen,
85746a97191SGreg Kroah-Hartman 				  u32 *buffer_actual_len,
85846a97191SGreg Kroah-Hartman 				  u64 *requestid);
85946a97191SGreg Kroah-Hartman 
86046a97191SGreg Kroah-Hartman extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
86146a97191SGreg Kroah-Hartman 				     void *buffer,
86246a97191SGreg Kroah-Hartman 				     u32 bufferlen,
86346a97191SGreg Kroah-Hartman 				     u32 *buffer_actual_len,
86446a97191SGreg Kroah-Hartman 				     u64 *requestid);
86546a97191SGreg Kroah-Hartman 
86646a97191SGreg Kroah-Hartman 
86746a97191SGreg Kroah-Hartman extern void vmbus_ontimer(unsigned long data);
86846a97191SGreg Kroah-Hartman 
86946a97191SGreg Kroah-Hartman /* Base driver object */
87046a97191SGreg Kroah-Hartman struct hv_driver {
87146a97191SGreg Kroah-Hartman 	const char *name;
87246a97191SGreg Kroah-Hartman 
87346a97191SGreg Kroah-Hartman 	/* the device type supported by this driver */
87446a97191SGreg Kroah-Hartman 	uuid_le dev_type;
87546a97191SGreg Kroah-Hartman 	const struct hv_vmbus_device_id *id_table;
87646a97191SGreg Kroah-Hartman 
87746a97191SGreg Kroah-Hartman 	struct device_driver driver;
87846a97191SGreg Kroah-Hartman 
87946a97191SGreg Kroah-Hartman 	int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *);
88046a97191SGreg Kroah-Hartman 	int (*remove)(struct hv_device *);
88146a97191SGreg Kroah-Hartman 	void (*shutdown)(struct hv_device *);
88246a97191SGreg Kroah-Hartman 
88346a97191SGreg Kroah-Hartman };
88446a97191SGreg Kroah-Hartman 
88546a97191SGreg Kroah-Hartman /* Base device object */
88646a97191SGreg Kroah-Hartman struct hv_device {
88746a97191SGreg Kroah-Hartman 	/* the device type id of this device */
88846a97191SGreg Kroah-Hartman 	uuid_le dev_type;
88946a97191SGreg Kroah-Hartman 
89046a97191SGreg Kroah-Hartman 	/* the device instance id of this device */
89146a97191SGreg Kroah-Hartman 	uuid_le dev_instance;
89246a97191SGreg Kroah-Hartman 
89346a97191SGreg Kroah-Hartman 	struct device device;
89446a97191SGreg Kroah-Hartman 
89546a97191SGreg Kroah-Hartman 	struct vmbus_channel *channel;
89646a97191SGreg Kroah-Hartman };
89746a97191SGreg Kroah-Hartman 
89846a97191SGreg Kroah-Hartman 
89946a97191SGreg Kroah-Hartman static inline struct hv_device *device_to_hv_device(struct device *d)
90046a97191SGreg Kroah-Hartman {
90146a97191SGreg Kroah-Hartman 	return container_of(d, struct hv_device, device);
90246a97191SGreg Kroah-Hartman }
90346a97191SGreg Kroah-Hartman 
90446a97191SGreg Kroah-Hartman static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
90546a97191SGreg Kroah-Hartman {
90646a97191SGreg Kroah-Hartman 	return container_of(d, struct hv_driver, driver);
90746a97191SGreg Kroah-Hartman }
90846a97191SGreg Kroah-Hartman 
90946a97191SGreg Kroah-Hartman static inline void hv_set_drvdata(struct hv_device *dev, void *data)
91046a97191SGreg Kroah-Hartman {
91146a97191SGreg Kroah-Hartman 	dev_set_drvdata(&dev->device, data);
91246a97191SGreg Kroah-Hartman }
91346a97191SGreg Kroah-Hartman 
91446a97191SGreg Kroah-Hartman static inline void *hv_get_drvdata(struct hv_device *dev)
91546a97191SGreg Kroah-Hartman {
91646a97191SGreg Kroah-Hartman 	return dev_get_drvdata(&dev->device);
91746a97191SGreg Kroah-Hartman }
91846a97191SGreg Kroah-Hartman 
91946a97191SGreg Kroah-Hartman /* Vmbus interface */
92046a97191SGreg Kroah-Hartman #define vmbus_driver_register(driver)	\
92146a97191SGreg Kroah-Hartman 	__vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
92246a97191SGreg Kroah-Hartman int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
92346a97191SGreg Kroah-Hartman 					 struct module *owner,
92446a97191SGreg Kroah-Hartman 					 const char *mod_name);
92546a97191SGreg Kroah-Hartman void vmbus_driver_unregister(struct hv_driver *hv_driver);
92646a97191SGreg Kroah-Hartman 
92746a97191SGreg Kroah-Hartman /**
92846a97191SGreg Kroah-Hartman  * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device
92946a97191SGreg Kroah-Hartman  *
93046a97191SGreg Kroah-Hartman  * This macro is used to create a struct hv_vmbus_device_id that matches a
93146a97191SGreg Kroah-Hartman  * specific device.
93246a97191SGreg Kroah-Hartman  */
93346a97191SGreg Kroah-Hartman #define VMBUS_DEVICE(g0, g1, g2, g3, g4, g5, g6, g7,	\
93446a97191SGreg Kroah-Hartman 		     g8, g9, ga, gb, gc, gd, ge, gf)	\
93546a97191SGreg Kroah-Hartman 	.guid = { g0, g1, g2, g3, g4, g5, g6, g7,	\
93646a97191SGreg Kroah-Hartman 		  g8, g9, ga, gb, gc, gd, ge, gf },
93746a97191SGreg Kroah-Hartman 
93846a97191SGreg Kroah-Hartman /*
9397fb96565SK. Y. Srinivasan  * GUID definitions of various offer types - services offered to the guest.
9407fb96565SK. Y. Srinivasan  */
9417fb96565SK. Y. Srinivasan 
9427fb96565SK. Y. Srinivasan /*
9437fb96565SK. Y. Srinivasan  * Network GUID
9447fb96565SK. Y. Srinivasan  * {f8615163-df3e-46c5-913f-f2d2f965ed0e}
9457fb96565SK. Y. Srinivasan  */
9467fb96565SK. Y. Srinivasan #define HV_NIC_GUID \
9477fb96565SK. Y. Srinivasan 	.guid = { \
9487fb96565SK. Y. Srinivasan 			0x63, 0x51, 0x61, 0xf8, 0x3e, 0xdf, 0xc5, 0x46, \
9497fb96565SK. Y. Srinivasan 			0x91, 0x3f, 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e \
9507fb96565SK. Y. Srinivasan 		}
9517fb96565SK. Y. Srinivasan 
9527fb96565SK. Y. Srinivasan /*
9537fb96565SK. Y. Srinivasan  * IDE GUID
9547fb96565SK. Y. Srinivasan  * {32412632-86cb-44a2-9b5c-50d1417354f5}
9557fb96565SK. Y. Srinivasan  */
9567fb96565SK. Y. Srinivasan #define HV_IDE_GUID \
9577fb96565SK. Y. Srinivasan 	.guid = { \
9587fb96565SK. Y. Srinivasan 			0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, \
9597fb96565SK. Y. Srinivasan 			0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 \
9607fb96565SK. Y. Srinivasan 		}
9617fb96565SK. Y. Srinivasan 
9627fb96565SK. Y. Srinivasan /*
9637fb96565SK. Y. Srinivasan  * SCSI GUID
9647fb96565SK. Y. Srinivasan  * {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
9657fb96565SK. Y. Srinivasan  */
9667fb96565SK. Y. Srinivasan #define HV_SCSI_GUID \
9677fb96565SK. Y. Srinivasan 	.guid = { \
9687fb96565SK. Y. Srinivasan 			0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, \
9697fb96565SK. Y. Srinivasan 			0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f \
9707fb96565SK. Y. Srinivasan 		}
9717fb96565SK. Y. Srinivasan 
9727fb96565SK. Y. Srinivasan /*
9737fb96565SK. Y. Srinivasan  * Shutdown GUID
9747fb96565SK. Y. Srinivasan  * {0e0b6031-5213-4934-818b-38d90ced39db}
9757fb96565SK. Y. Srinivasan  */
9767fb96565SK. Y. Srinivasan #define HV_SHUTDOWN_GUID \
9777fb96565SK. Y. Srinivasan 	.guid = { \
9787fb96565SK. Y. Srinivasan 			0x31, 0x60, 0x0b, 0x0e, 0x13, 0x52, 0x34, 0x49, \
9797fb96565SK. Y. Srinivasan 			0x81, 0x8b, 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb \
9807fb96565SK. Y. Srinivasan 		}
9817fb96565SK. Y. Srinivasan 
9827fb96565SK. Y. Srinivasan /*
9837fb96565SK. Y. Srinivasan  * Time Synch GUID
9847fb96565SK. Y. Srinivasan  * {9527E630-D0AE-497b-ADCE-E80AB0175CAF}
9857fb96565SK. Y. Srinivasan  */
9867fb96565SK. Y. Srinivasan #define HV_TS_GUID \
9877fb96565SK. Y. Srinivasan 	.guid = { \
9887fb96565SK. Y. Srinivasan 			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, \
9897fb96565SK. Y. Srinivasan 			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf \
9907fb96565SK. Y. Srinivasan 		}
9917fb96565SK. Y. Srinivasan 
9927fb96565SK. Y. Srinivasan /*
9937fb96565SK. Y. Srinivasan  * Heartbeat GUID
9947fb96565SK. Y. Srinivasan  * {57164f39-9115-4e78-ab55-382f3bd5422d}
9957fb96565SK. Y. Srinivasan  */
9967fb96565SK. Y. Srinivasan #define HV_HEART_BEAT_GUID \
9977fb96565SK. Y. Srinivasan 	.guid = { \
9987fb96565SK. Y. Srinivasan 			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, \
9997fb96565SK. Y. Srinivasan 			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d \
10007fb96565SK. Y. Srinivasan 		}
10017fb96565SK. Y. Srinivasan 
10027fb96565SK. Y. Srinivasan /*
10037fb96565SK. Y. Srinivasan  * KVP GUID
10047fb96565SK. Y. Srinivasan  * {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}
10057fb96565SK. Y. Srinivasan  */
10067fb96565SK. Y. Srinivasan #define HV_KVP_GUID \
10077fb96565SK. Y. Srinivasan 	.guid = { \
10087fb96565SK. Y. Srinivasan 			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, \
10097fb96565SK. Y. Srinivasan 			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6 \
10107fb96565SK. Y. Srinivasan 		}
10117fb96565SK. Y. Srinivasan 
10127fb96565SK. Y. Srinivasan /*
10137fb96565SK. Y. Srinivasan  * Dynamic memory GUID
10147fb96565SK. Y. Srinivasan  * {525074dc-8985-46e2-8057-a307dc18a502}
10157fb96565SK. Y. Srinivasan  */
10167fb96565SK. Y. Srinivasan #define HV_DM_GUID \
10177fb96565SK. Y. Srinivasan 	.guid = { \
10187fb96565SK. Y. Srinivasan 			0xdc, 0x74, 0x50, 0X52, 0x85, 0x89, 0xe2, 0x46, \
10197fb96565SK. Y. Srinivasan 			0x80, 0x57, 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02 \
10207fb96565SK. Y. Srinivasan 		}
10217fb96565SK. Y. Srinivasan 
10227fb96565SK. Y. Srinivasan /*
10237fb96565SK. Y. Srinivasan  * Mouse GUID
10247fb96565SK. Y. Srinivasan  * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}
10257fb96565SK. Y. Srinivasan  */
10267fb96565SK. Y. Srinivasan #define HV_MOUSE_GUID \
10277fb96565SK. Y. Srinivasan 	.guid = { \
10287fb96565SK. Y. Srinivasan 			0x9e, 0xb6, 0xa8, 0xcf, 0x4a, 0x5b, 0xc0, 0x4c, \
10297fb96565SK. Y. Srinivasan 			0xb9, 0x8b, 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a \
10307fb96565SK. Y. Srinivasan 		}
10317fb96565SK. Y. Srinivasan 
10327fb96565SK. Y. Srinivasan /*
103396dd86faSK. Y. Srinivasan  * VSS (Backup/Restore) GUID
103496dd86faSK. Y. Srinivasan  */
103596dd86faSK. Y. Srinivasan #define HV_VSS_GUID \
103696dd86faSK. Y. Srinivasan 	.guid = { \
103796dd86faSK. Y. Srinivasan 			0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42, \
103896dd86faSK. Y. Srinivasan 			0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4,  0x40 \
103996dd86faSK. Y. Srinivasan 		}
104096dd86faSK. Y. Srinivasan /*
104168a2d20bSHaiyang Zhang  * Synthetic Video GUID
104268a2d20bSHaiyang Zhang  * {DA0A7802-E377-4aac-8E77-0558EB1073F8}
104368a2d20bSHaiyang Zhang  */
104468a2d20bSHaiyang Zhang #define HV_SYNTHVID_GUID \
104568a2d20bSHaiyang Zhang 	.guid = { \
104668a2d20bSHaiyang Zhang 			0x02, 0x78, 0x0a, 0xda, 0x77, 0xe3, 0xac, 0x4a, \
104768a2d20bSHaiyang Zhang 			0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 \
104868a2d20bSHaiyang Zhang 		}
104968a2d20bSHaiyang Zhang 
105068a2d20bSHaiyang Zhang /*
105198b80d89SK. Y. Srinivasan  * Synthetic FC GUID
105298b80d89SK. Y. Srinivasan  * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda}
105398b80d89SK. Y. Srinivasan  */
105498b80d89SK. Y. Srinivasan #define HV_SYNTHFC_GUID \
105598b80d89SK. Y. Srinivasan 	.guid = { \
105698b80d89SK. Y. Srinivasan 			0x4A, 0xCC, 0x9B, 0x2F, 0x69, 0x00, 0xF3, 0x4A, \
105798b80d89SK. Y. Srinivasan 			0xB7, 0x6B, 0x6F, 0xD0, 0xBE, 0x52, 0x8C, 0xDA \
105898b80d89SK. Y. Srinivasan 		}
105998b80d89SK. Y. Srinivasan 
106098b80d89SK. Y. Srinivasan /*
106101325476SK. Y. Srinivasan  * Guest File Copy Service
106201325476SK. Y. Srinivasan  * {34D14BE3-DEE4-41c8-9AE7-6B174977C192}
106301325476SK. Y. Srinivasan  */
106401325476SK. Y. Srinivasan 
106501325476SK. Y. Srinivasan #define HV_FCOPY_GUID \
106601325476SK. Y. Srinivasan 	.guid = { \
106701325476SK. Y. Srinivasan 			0xE3, 0x4B, 0xD1, 0x34, 0xE4, 0xDE, 0xC8, 0x41, \
106801325476SK. Y. Srinivasan 			0x9A, 0xE7, 0x6B, 0x17, 0x49, 0x77, 0xC1, 0x92 \
106901325476SK. Y. Srinivasan 		}
107001325476SK. Y. Srinivasan 
107101325476SK. Y. Srinivasan /*
107246a97191SGreg Kroah-Hartman  * Common header for Hyper-V ICs
107346a97191SGreg Kroah-Hartman  */
107446a97191SGreg Kroah-Hartman 
107546a97191SGreg Kroah-Hartman #define ICMSGTYPE_NEGOTIATE		0
107646a97191SGreg Kroah-Hartman #define ICMSGTYPE_HEARTBEAT		1
107746a97191SGreg Kroah-Hartman #define ICMSGTYPE_KVPEXCHANGE		2
107846a97191SGreg Kroah-Hartman #define ICMSGTYPE_SHUTDOWN		3
107946a97191SGreg Kroah-Hartman #define ICMSGTYPE_TIMESYNC		4
108046a97191SGreg Kroah-Hartman #define ICMSGTYPE_VSS			5
108146a97191SGreg Kroah-Hartman 
108246a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_TRANSACTION	1
108346a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_REQUEST		2
108446a97191SGreg Kroah-Hartman #define ICMSGHDRFLAG_RESPONSE		4
108546a97191SGreg Kroah-Hartman 
108646a97191SGreg Kroah-Hartman 
108746a97191SGreg Kroah-Hartman /*
108846a97191SGreg Kroah-Hartman  * While we want to handle util services as regular devices,
108946a97191SGreg Kroah-Hartman  * there is only one instance of each of these services; so
109046a97191SGreg Kroah-Hartman  * we statically allocate the service specific state.
109146a97191SGreg Kroah-Hartman  */
109246a97191SGreg Kroah-Hartman 
109346a97191SGreg Kroah-Hartman struct hv_util_service {
109446a97191SGreg Kroah-Hartman 	u8 *recv_buffer;
109546a97191SGreg Kroah-Hartman 	void (*util_cb)(void *);
109646a97191SGreg Kroah-Hartman 	int (*util_init)(struct hv_util_service *);
109746a97191SGreg Kroah-Hartman 	void (*util_deinit)(void);
109846a97191SGreg Kroah-Hartman };
109946a97191SGreg Kroah-Hartman 
110046a97191SGreg Kroah-Hartman struct vmbuspipe_hdr {
110146a97191SGreg Kroah-Hartman 	u32 flags;
110246a97191SGreg Kroah-Hartman 	u32 msgsize;
110346a97191SGreg Kroah-Hartman } __packed;
110446a97191SGreg Kroah-Hartman 
110546a97191SGreg Kroah-Hartman struct ic_version {
110646a97191SGreg Kroah-Hartman 	u16 major;
110746a97191SGreg Kroah-Hartman 	u16 minor;
110846a97191SGreg Kroah-Hartman } __packed;
110946a97191SGreg Kroah-Hartman 
111046a97191SGreg Kroah-Hartman struct icmsg_hdr {
111146a97191SGreg Kroah-Hartman 	struct ic_version icverframe;
111246a97191SGreg Kroah-Hartman 	u16 icmsgtype;
111346a97191SGreg Kroah-Hartman 	struct ic_version icvermsg;
111446a97191SGreg Kroah-Hartman 	u16 icmsgsize;
111546a97191SGreg Kroah-Hartman 	u32 status;
111646a97191SGreg Kroah-Hartman 	u8 ictransaction_id;
111746a97191SGreg Kroah-Hartman 	u8 icflags;
111846a97191SGreg Kroah-Hartman 	u8 reserved[2];
111946a97191SGreg Kroah-Hartman } __packed;
112046a97191SGreg Kroah-Hartman 
112146a97191SGreg Kroah-Hartman struct icmsg_negotiate {
112246a97191SGreg Kroah-Hartman 	u16 icframe_vercnt;
112346a97191SGreg Kroah-Hartman 	u16 icmsg_vercnt;
112446a97191SGreg Kroah-Hartman 	u32 reserved;
112546a97191SGreg Kroah-Hartman 	struct ic_version icversion_data[1]; /* any size array */
112646a97191SGreg Kroah-Hartman } __packed;
112746a97191SGreg Kroah-Hartman 
112846a97191SGreg Kroah-Hartman struct shutdown_msg_data {
112946a97191SGreg Kroah-Hartman 	u32 reason_code;
113046a97191SGreg Kroah-Hartman 	u32 timeout_seconds;
113146a97191SGreg Kroah-Hartman 	u32 flags;
113246a97191SGreg Kroah-Hartman 	u8  display_message[2048];
113346a97191SGreg Kroah-Hartman } __packed;
113446a97191SGreg Kroah-Hartman 
113546a97191SGreg Kroah-Hartman struct heartbeat_msg_data {
113646a97191SGreg Kroah-Hartman 	u64 seq_num;
113746a97191SGreg Kroah-Hartman 	u32 reserved[8];
113846a97191SGreg Kroah-Hartman } __packed;
113946a97191SGreg Kroah-Hartman 
114046a97191SGreg Kroah-Hartman /* Time Sync IC defs */
114146a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_PROBE	0
114246a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_SYNC	1
114346a97191SGreg Kroah-Hartman #define ICTIMESYNCFLAG_SAMPLE	2
114446a97191SGreg Kroah-Hartman 
114546a97191SGreg Kroah-Hartman #ifdef __x86_64__
114646a97191SGreg Kroah-Hartman #define WLTIMEDELTA	116444736000000000L	/* in 100ns unit */
114746a97191SGreg Kroah-Hartman #else
114846a97191SGreg Kroah-Hartman #define WLTIMEDELTA	116444736000000000LL
114946a97191SGreg Kroah-Hartman #endif
115046a97191SGreg Kroah-Hartman 
115146a97191SGreg Kroah-Hartman struct ictimesync_data {
115246a97191SGreg Kroah-Hartman 	u64 parenttime;
115346a97191SGreg Kroah-Hartman 	u64 childtime;
115446a97191SGreg Kroah-Hartman 	u64 roundtriptime;
115546a97191SGreg Kroah-Hartman 	u8 flags;
115646a97191SGreg Kroah-Hartman } __packed;
115746a97191SGreg Kroah-Hartman 
115846a97191SGreg Kroah-Hartman struct hyperv_service_callback {
115946a97191SGreg Kroah-Hartman 	u8 msg_type;
116046a97191SGreg Kroah-Hartman 	char *log_msg;
116146a97191SGreg Kroah-Hartman 	uuid_le data;
116246a97191SGreg Kroah-Hartman 	struct vmbus_channel *channel;
116346a97191SGreg Kroah-Hartman 	void (*callback) (void *context);
116446a97191SGreg Kroah-Hartman };
116546a97191SGreg Kroah-Hartman 
1166c836d0abSK. Y. Srinivasan #define MAX_SRV_VER	0x7ffffff
11676741335bSK. Y. Srinivasan extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
1168c836d0abSK. Y. Srinivasan 					struct icmsg_negotiate *, u8 *, int,
1169c836d0abSK. Y. Srinivasan 					int);
117046a97191SGreg Kroah-Hartman 
11712939437cSK. Y. Srinivasan int hv_kvp_init(struct hv_util_service *);
11722939437cSK. Y. Srinivasan void hv_kvp_deinit(void);
11732939437cSK. Y. Srinivasan void hv_kvp_onchannelcallback(void *);
11742939437cSK. Y. Srinivasan 
117596dd86faSK. Y. Srinivasan int hv_vss_init(struct hv_util_service *);
117696dd86faSK. Y. Srinivasan void hv_vss_deinit(void);
117796dd86faSK. Y. Srinivasan void hv_vss_onchannelcallback(void *);
117896dd86faSK. Y. Srinivasan 
117990eedf0cSGerd Hoffmann extern struct resource hyperv_mmio;
118090f34535SK. Y. Srinivasan 
118137f7278bSK. Y. Srinivasan /*
118237f7278bSK. Y. Srinivasan  * Negotiated version with the Host.
118337f7278bSK. Y. Srinivasan  */
118437f7278bSK. Y. Srinivasan 
118537f7278bSK. Y. Srinivasan extern __u32 vmbus_proto_version;
118637f7278bSK. Y. Srinivasan 
118746a97191SGreg Kroah-Hartman #endif /* _HYPERV_H */
1188