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