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