hyperv.h revision 250200
1250079Scarl/*- 2250079Scarl * Copyright (c) 2009-2012 Microsoft Corp. 3289542Scem * Copyright (c) 2012 NetApp Inc. 4250079Scarl * Copyright (c) 2012 Citrix Inc. 5250079Scarl * All rights reserved. 6250079Scarl * 7250079Scarl * Redistribution and use in source and binary forms, with or without 8250079Scarl * modification, are permitted provided that the following conditions 9250079Scarl * are met: 10250079Scarl * 1. Redistributions of source code must retain the above copyright 11250079Scarl * notice unmodified, this list of conditions, and the following 12250079Scarl * disclaimer. 13250079Scarl * 2. Redistributions in binary form must reproduce the above copyright 14250079Scarl * notice, this list of conditions and the following disclaimer in the 15250079Scarl * documentation and/or other materials provided with the distribution. 16250079Scarl * 17250079Scarl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18250079Scarl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19250079Scarl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20250079Scarl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21250079Scarl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22250079Scarl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23250079Scarl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24250079Scarl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25250079Scarl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26250079Scarl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27250079Scarl */ 28250079Scarl 29250079Scarl/** 30250079Scarl * HyperV definitions for messages that are sent between instances of the 31250079Scarl * Channel Management Library in separate partitions, or in some cases, 32250079Scarl * back to itself. 33250079Scarl */ 34250079Scarl 35250079Scarl#ifndef __HYPERV_H__ 36250079Scarl#define __HYPERV_H__ 37250079Scarl 38250079Scarl#include <sys/param.h> 39289207Scem#include <sys/mbuf.h> 40250079Scarl#include <sys/queue.h> 41250079Scarl#include <sys/malloc.h> 42250079Scarl#include <sys/kthread.h> 43250079Scarl#include <sys/taskqueue.h> 44250079Scarl#include <sys/systm.h> 45250079Scarl#include <sys/lock.h> 46250079Scarl#include <sys/sema.h> 47250079Scarl#include <sys/mutex.h> 48250079Scarl#include <sys/bus.h> 49250079Scarl#include <vm/vm.h> 50250079Scarl#include <vm/vm_param.h> 51250079Scarl#include <vm/pmap.h> 52250079Scarl 53250079Scarl#include <amd64/include/xen/synch_bitops.h> 54250079Scarl#include <amd64/include/atomic.h> 55250079Scarl 56250079Scarltypedef uint8_t hv_bool_uint8_t; 57250079Scarl 58250079Scarl#define HV_S_OK 0x00000000 59250079Scarl#define HV_E_FAIL 0x80004005 60250079Scarl#define HV_ERROR_NOT_SUPPORTED 0x80070032 61250079Scarl#define HV_ERROR_MACHINE_LOCKED 0x800704F7 62250079Scarl 63289648Scem/* 64250079Scarl * A revision number of vmbus that is used for ensuring both ends on a 65289539Scem * partition are using compatible versions. 66289648Scem */ 67250079Scarl 68250079Scarl#define HV_VMBUS_REVISION_NUMBER 13 69250079Scarl 70250079Scarl/* 71250079Scarl * Make maximum size of pipe payload of 16K 72289648Scem */ 73250079Scarl 74250079Scarl#define HV_MAX_PIPE_DATA_PAYLOAD (sizeof(BYTE) * 16384) 75289610Scem 76289610Scem/* 77289610Scem * Define pipe_mode values 78289610Scem */ 79289610Scem 80289610Scem#define HV_VMBUS_PIPE_TYPE_BYTE 0x00000000 81289610Scem#define HV_VMBUS_PIPE_TYPE_MESSAGE 0x00000004 82289610Scem 83289610Scem/* 84289610Scem * The size of the user defined data buffer for non-pipe offers 85289610Scem */ 86289610Scem 87289539Scem#define HV_MAX_USER_DEFINED_BYTES 120 88289539Scem 89289539Scem/* 90289539Scem * The size of the user defined data buffer for pipe offers 91289539Scem */ 92289539Scem 93289539Scem#define HV_MAX_PIPE_USER_DEFINED_BYTES 116 94289539Scem 95255274Scarl 96255274Scarl#define HV_MAX_PAGE_BUFFER_COUNT 16 97255274Scarl#define HV_MAX_MULTIPAGE_BUFFER_COUNT 32 98255274Scarl 99250079Scarl#define HV_ALIGN_UP(value, align) \ 100250079Scarl (((value) & (align-1)) ? \ 101255274Scarl (((value) + (align-1)) & ~(align-1) ) : (value)) 102250079Scarl 103289397Scem#define HV_ALIGN_DOWN(value, align) ( (value) & ~(align-1) ) 104250079Scarl 105250079Scarl#define HV_NUM_PAGES_SPANNED(addr, len) \ 106250079Scarl ((HV_ALIGN_UP(addr+len, PAGE_SIZE) - \ 107250079Scarl HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT ) 108250079Scarl 109250079Scarltypedef struct hv_guid { 110250079Scarl unsigned char data[16]; 111250079Scarl} __packed hv_guid; 112250079Scarl 113250079Scarl/* 114289543Scem * At the center of the Channel Management library is 115289543Scem * the Channel Offer. This struct contains the 116289543Scem * fundamental information about an offer. 117289543Scem */ 118289543Scem 119250079Scarltypedef struct hv_vmbus_channel_offer { 120250079Scarl hv_guid interface_type; 121250079Scarl hv_guid interface_instance; 122250079Scarl uint64_t interrupt_latency_in_100ns_units; 123250079Scarl uint32_t interface_revision; 124250079Scarl uint32_t server_context_area_size; /* in bytes */ 125250079Scarl uint16_t channel_flags; 126250079Scarl uint16_t mmio_megabytes; /* in bytes * 1024 * 1024 */ 127289546Scem union 128250079Scarl { 129289546Scem /* 130250079Scarl * Non-pipes: The user has HV_MAX_USER_DEFINED_BYTES bytes. 131250079Scarl */ 132289542Scem struct { 133289542Scem uint8_t user_defined[HV_MAX_USER_DEFINED_BYTES]; 134289542Scem } __packed standard; 135289542Scem 136289542Scem /* 137289542Scem * Pipes: The following structure is an integrated pipe protocol, which 138289542Scem * is implemented on top of standard user-defined data. pipe 139289542Scem * clients have HV_MAX_PIPE_USER_DEFINED_BYTES left for their 140289542Scem * own use. 141289542Scem */ 142289542Scem struct { 143289542Scem uint32_t pipe_mode; 144289542Scem uint8_t user_defined[HV_MAX_PIPE_USER_DEFINED_BYTES]; 145289542Scem } __packed pipe; 146289546Scem } u; 147289546Scem 148289546Scem uint32_t padding; 149289546Scem 150289546Scem} __packed hv_vmbus_channel_offer; 151289546Scem 152289546Scemtypedef uint32_t hv_gpadl_handle; 153289546Scem 154289546Scemtypedef struct { 155289546Scem uint16_t type; 156289546Scem uint16_t data_offset8; 157289546Scem uint16_t length8; 158289542Scem uint16_t flags; 159289542Scem uint64_t transaction_id; 160289542Scem} __packed hv_vm_packet_descriptor; 161289542Scem 162289542Scemtypedef uint32_t hv_previous_packet_offset; 163289542Scem 164289542Scemtypedef struct { 165289542Scem hv_previous_packet_offset previous_packet_start_offset; 166289542Scem hv_vm_packet_descriptor descriptor; 167289542Scem} __packed hv_vm_packet_header; 168250079Scarl 169250079Scarltypedef struct { 170250079Scarl uint32_t byte_count; 171255274Scarl uint32_t byte_offset; 172250079Scarl} __packed hv_vm_transfer_page; 173250079Scarl 174250079Scarltypedef struct { 175250079Scarl hv_vm_packet_descriptor d; 176250079Scarl uint16_t transfer_page_set_id; 177250079Scarl hv_bool_uint8_t sender_owns_set; 178250079Scarl uint8_t reserved; 179250079Scarl uint32_t range_count; 180289546Scem hv_vm_transfer_page ranges[1]; 181289546Scem} __packed hv_vm_transfer_page_packet_header; 182289546Scem 183289546Scemtypedef struct { 184289546Scem hv_vm_packet_descriptor d; 185289546Scem uint32_t gpadl; 186289546Scem uint32_t reserved; 187250079Scarl} __packed hv_vm_gpadl_packet_header; 188289610Scem 189289610Scemtypedef struct { 190289610Scem hv_vm_packet_descriptor d; 191289539Scem uint32_t gpadl; 192289542Scem uint16_t transfer_page_set_id; 193289542Scem uint16_t reserved; 194289542Scem} __packed hv_vm_add_remove_transfer_page_set; 195289543Scem 196289542Scem/* 197289542Scem * This structure defines a range in guest 198289539Scem * physical space that can be made 199289539Scem * to look virtually contiguous. 200289539Scem */ 201289539Scem 202289539Scemtypedef struct { 203289542Scem uint32_t byte_count; 204289546Scem uint32_t byte_offset; 205289546Scem uint64_t pfn_array[0]; 206289546Scem} __packed hv_gpa_range; 207289546Scem 208289542Scem/* 209289542Scem * This is the format for an Establish Gpadl packet, which contains a handle 210289546Scem * by which this GPADL will be known and a set of GPA ranges associated with 211289546Scem * it. This can be converted to a MDL by the guest OS. If there are multiple 212289542Scem * GPA ranges, then the resulting MDL will be "chained," representing multiple 213289542Scem * VA ranges. 214289542Scem */ 215289546Scem 216289542Scemtypedef struct { 217289542Scem hv_vm_packet_descriptor d; 218289542Scem uint32_t gpadl; 219289542Scem uint32_t range_count; 220289542Scem hv_gpa_range range[1]; 221289542Scem} __packed hv_vm_establish_gpadl; 222289542Scem 223250079Scarl/* 224250079Scarl * This is the format for a Teardown Gpadl packet, which indicates that the 225289234Scem * GPADL handle in the Establish Gpadl packet will never be referenced again. 226289234Scem */ 227289234Scem 228289234Scemtypedef struct { 229289234Scem hv_vm_packet_descriptor d; 230289234Scem uint32_t gpadl; 231289234Scem /* for alignment to a 8-byte boundary */ 232289234Scem uint32_t reserved; 233289234Scem} __packed hv_vm_teardown_gpadl; 234289234Scem 235289234Scem/* 236289234Scem * This is the format for a GPA-Direct packet, which contains a set of GPA 237289234Scem * ranges, in addition to commands and/or data. 238289234Scem */ 239289234Scem 240289234Scemtypedef struct { 241289234Scem hv_vm_packet_descriptor d; 242289234Scem uint32_t reserved; 243289234Scem uint32_t range_count; 244289234Scem hv_gpa_range range[1]; 245255279Scarl} __packed hv_vm_data_gpa_direct; 246255279Scarl 247255279Scarl/* 248255279Scarl * This is the format for a Additional data Packet. 249255279Scarl */ 250255279Scarltypedef struct { 251255279Scarl hv_vm_packet_descriptor d; 252250079Scarl uint64_t total_bytes; 253255279Scarl uint32_t byte_offset; 254289397Scem uint32_t byte_count; 255289542Scem uint8_t data[1]; 256255279Scarl} __packed hv_vm_additional_data; 257289542Scem 258289397Scemtypedef union { 259250079Scarl hv_vm_packet_descriptor simple_header; 260250079Scarl hv_vm_transfer_page_packet_header transfer_page_header; 261250079Scarl hv_vm_gpadl_packet_header gpadl_header; 262250079Scarl hv_vm_add_remove_transfer_page_set add_remove_transfer_page_header; 263289539Scem hv_vm_establish_gpadl establish_gpadl_header; 264289546Scem hv_vm_teardown_gpadl teardown_gpadl_header; 265289546Scem hv_vm_data_gpa_direct data_gpa_direct_header; 266289546Scem} __packed hv_vm_packet_largest_possible_header; 267255272Scarl 268289647Scemtypedef enum { 269289647Scem HV_VMBUS_PACKET_TYPE_INVALID = 0x0, 270255272Scarl HV_VMBUS_PACKET_TYPES_SYNCH = 0x1, 271255272Scarl HV_VMBUS_PACKET_TYPE_ADD_TRANSFER_PAGE_SET = 0x2, 272255272Scarl HV_VMBUS_PACKET_TYPE_REMOVE_TRANSFER_PAGE_SET = 0x3, 273250079Scarl HV_VMBUS_PACKET_TYPE_ESTABLISH_GPADL = 0x4, 274289344Scem HV_VMBUS_PACKET_TYPE_TEAR_DOWN_GPADL = 0x5, 275289540Scem HV_VMBUS_PACKET_TYPE_DATA_IN_BAND = 0x6, 276289342Scem HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES = 0x7, 277289540Scem HV_VMBUS_PACKET_TYPE_DATA_USING_GPADL = 0x8, 278250079Scarl HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT = 0x9, 279289540Scem HV_VMBUS_PACKET_TYPE_CANCEL_REQUEST = 0xa, 280289546Scem HV_VMBUS_PACKET_TYPE_COMPLETION = 0xb, 281289546Scem HV_VMBUS_PACKET_TYPE_DATA_USING_ADDITIONAL_PACKETS = 0xc, 282289546Scem HV_VMBUS_PACKET_TYPE_ADDITIONAL_DATA = 0xd 283289546Scem} hv_vmbus_packet_type; 284289546Scem 285289546Scem#define HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED 1 286289546Scem 287250079Scarl/* 288289397Scem * Version 1 messages 289289348Scem */ 290289648Scemtypedef enum { 291289542Scem HV_CHANNEL_MESSAGE_INVALID = 0, 292289648Scem HV_CHANNEL_MESSAGE_OFFER_CHANNEL = 1, 293289272Scem HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER = 2, 294289648Scem HV_CHANNEL_MESSAGE_REQUEST_OFFERS = 3, 295289543Scem HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED = 4, 296289543Scem HV_CHANNEL_MESSAGE_OPEN_CHANNEL = 5, 297289543Scem HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT = 6, 298289543Scem HV_CHANNEL_MESSAGE_CLOSE_CHANNEL = 7, 299289543Scem HV_CHANNEL_MESSAGEL_GPADL_HEADER = 8, 300289543Scem HV_CHANNEL_MESSAGE_GPADL_BODY = 9, 301289542Scem HV_CHANNEL_MESSAGE_GPADL_CREATED = 10, 302289542Scem HV_CHANNEL_MESSAGE_GPADL_TEARDOWN = 11, 303289546Scem HV_CHANNEL_MESSAGE_GPADL_TORNDOWN = 12, 304289648Scem HV_CHANNEL_MESSAGE_REL_ID_RELEASED = 13, 305289546Scem HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14, 306289546Scem HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15, 307289648Scem HV_CHANNEL_MESSAGE_UNLOAD = 16, 308289546Scem 309289648Scem#ifdef HV_VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD 310289546Scem HV_CHANNEL_MESSAGE_VIEW_RANGE_ADD = 17, 311255274Scarl HV_CHANNEL_MESSAGE_VIEW_RANGE_REMOVE = 18, 312250079Scarl#endif 313250079Scarl HV_CHANNEL_MESSAGE_COUNT 314289612Scem} hv_vmbus_channel_msg_type; 315289612Scem 316289648Scemtypedef struct { 317289233Scem hv_vmbus_channel_msg_type message_type; 318289233Scem uint32_t padding; 319289538Scem} __packed hv_vmbus_channel_msg_header; 320289233Scem 321289538Scem/* 322289233Scem * Query VMBus Version parameters 323289538Scem */ 324289538Scemtypedef struct { 325289233Scem hv_vmbus_channel_msg_header header; 326289538Scem uint32_t version; 327289538Scem} __packed hv_vmbus_channel_query_vmbus_version; 328289233Scem 329289538Scem/* 330289538Scem * VMBus Version Supported parameters 331289233Scem */ 332289648Scemtypedef struct { 333250079Scarl hv_vmbus_channel_msg_header header; 334250079Scarl hv_bool_uint8_t version_supported; 335289648Scem} __packed hv_vmbus_channel_version_supported; 336289648Scem 337289648Scem/* 338289542Scem * Channel Offer parameters 339289542Scem */ 340289542Scemtypedef struct { 341289542Scem hv_vmbus_channel_msg_header header; 342289648Scem hv_vmbus_channel_offer offer; 343289648Scem uint32_t child_rel_id; 344289648Scem uint8_t monitor_id; 345289648Scem hv_bool_uint8_t monitor_allocated; 346289607Scem} __packed hv_vmbus_channel_offer_channel; 347289607Scem 348289648Scem/* 349289648Scem * Rescind Offer parameters 350289648Scem */ 351289542Scemtypedef struct 352289542Scem{ 353289648Scem hv_vmbus_channel_msg_header header; 354289542Scem uint32_t child_rel_id; 355289542Scem} __packed hv_vmbus_channel_rescind_offer; 356289648Scem 357289648Scem 358289648Scem/* 359289546Scem * Request Offer -- no parameters, SynIC message contains the partition ID 360289648Scem * 361289648Scem * Set Snoop -- no parameters, SynIC message contains the partition ID 362289542Scem * 363289546Scem * Clear Snoop -- no parameters, SynIC message contains the partition ID 364289648Scem * 365289648Scem * All Offers Delivered -- no parameters, SynIC message contains the 366289542Scem * partition ID 367289542Scem * 368289542Scem * Flush Client -- no parameters, SynIC message contains the partition ID 369289542Scem */ 370289542Scem 371289542Scem 372289542Scem/* 373289542Scem * Open Channel parameters 374289542Scem */ 375289607Scemtypedef struct 376289607Scem{ 377289607Scem hv_vmbus_channel_msg_header header; 378289607Scem 379289607Scem /* 380289607Scem * Identifies the specific VMBus channel that is being opened. 381289542Scem */ 382289542Scem uint32_t child_rel_id; 383289542Scem 384289542Scem /* 385289542Scem * ID making a particular open request at a channel offer unique. 386289542Scem */ 387289542Scem uint32_t open_id; 388289546Scem 389289546Scem /* 390289546Scem * GPADL for the channel's ring buffer. 391289546Scem */ 392289542Scem hv_gpadl_handle ring_buffer_gpadl_handle; 393289546Scem 394289546Scem /* 395289546Scem * GPADL for the channel's server context save area. 396289542Scem */ 397289546Scem hv_gpadl_handle server_context_area_gpadl_handle; 398289546Scem 399289542Scem /* 400289542Scem * The upstream ring buffer begins at offset zero in the memory described 401289614Scem * by ring_buffer_gpadl_handle. The downstream ring buffer follows it at 402289542Scem * this offset (in pages). 403289542Scem */ 404289542Scem uint32_t downstream_ring_buffer_page_offset; 405289542Scem 406289542Scem /* 407289542Scem * User-specific data to be passed along to the server endpoint. 408289542Scem */ 409289614Scem uint8_t user_data[HV_MAX_USER_DEFINED_BYTES]; 410289542Scem 411289542Scem} __packed hv_vmbus_channel_open_channel; 412289542Scem 413289542Scemtypedef uint32_t hv_nt_status; 414289542Scem 415289542Scem/* 416289542Scem * Open Channel Result parameters 417289614Scem */ 418289614Scemtypedef struct 419289614Scem{ 420289614Scem hv_vmbus_channel_msg_header header; 421289614Scem uint32_t child_rel_id; 422289614Scem uint32_t open_id; 423289614Scem hv_nt_status status; 424289614Scem} __packed hv_vmbus_channel_open_result; 425289614Scem 426289614Scem/* 427289614Scem * Close channel parameters 428289614Scem */ 429289614Scemtypedef struct 430289614Scem{ 431289646Scem hv_vmbus_channel_msg_header header; 432289614Scem uint32_t child_rel_id; 433289614Scem} __packed hv_vmbus_channel_close_channel; 434289614Scem 435289614Scem/* 436289614Scem * Channel Message GPADL 437289614Scem */ 438289614Scem#define HV_GPADL_TYPE_RING_BUFFER 1 439289614Scem#define HV_GPADL_TYPE_SERVER_SAVE_AREA 2 440289614Scem#define HV_GPADL_TYPE_TRANSACTION 8 441289614Scem 442289614Scem/* 443289614Scem * The number of PFNs in a GPADL message is defined by the number of pages 444289614Scem * that would be spanned by byte_count and byte_offset. If the implied number 445289646Scem * of PFNs won't fit in this packet, there will be a follow-up packet that 446289614Scem * contains more 447289614Scem */ 448250079Scarl 449250079Scarltypedef struct { 450250079Scarl hv_vmbus_channel_msg_header header; 451250079Scarl uint32_t child_rel_id; 452250079Scarl uint32_t gpadl; 453250079Scarl uint16_t range_buf_len; 454250079Scarl uint16_t range_count; 455250079Scarl hv_gpa_range range[0]; 456250079Scarl} __packed hv_vmbus_channel_gpadl_header; 457250079Scarl 458250079Scarl/* 459250079Scarl * This is the follow-up packet that contains more PFNs 460250079Scarl */ 461250079Scarltypedef struct { 462250079Scarl hv_vmbus_channel_msg_header header; 463250079Scarl uint32_t message_number; 464250079Scarl uint32_t gpadl; 465250079Scarl uint64_t pfn[0]; 466250079Scarl} __packed hv_vmbus_channel_gpadl_body; 467250079Scarl 468250079Scarltypedef struct { 469250079Scarl hv_vmbus_channel_msg_header header; 470250079Scarl uint32_t child_rel_id; 471289207Scem uint32_t gpadl; 472289207Scem uint32_t creation_status; 473250079Scarl} __packed hv_vmbus_channel_gpadl_created; 474250079Scarl 475250079Scarltypedef struct { 476250079Scarl hv_vmbus_channel_msg_header header; 477250079Scarl uint32_t child_rel_id; 478250079Scarl uint32_t gpadl; 479289209Scem} __packed hv_vmbus_channel_gpadl_teardown; 480250079Scarl 481289209Scemtypedef struct { 482289209Scem hv_vmbus_channel_msg_header header; 483250079Scarl uint32_t gpadl; 484289209Scem} __packed hv_vmbus_channel_gpadl_torndown; 485289209Scem 486289209Scemtypedef struct { 487250079Scarl hv_vmbus_channel_msg_header header; 488250079Scarl uint32_t child_rel_id; 489250079Scarl} __packed hv_vmbus_channel_relid_released; 490250079Scarl 491250079Scarltypedef struct { 492289209Scem hv_vmbus_channel_msg_header header; 493289209Scem uint32_t vmbus_version_requested; 494250079Scarl uint32_t padding2; 495250079Scarl uint64_t interrupt_page; 496289209Scem uint64_t monitor_page_1; 497289209Scem uint64_t monitor_page_2; 498289209Scem} __packed hv_vmbus_channel_initiate_contact; 499250079Scarl 500250079Scarltypedef struct { 501255274Scarl hv_vmbus_channel_msg_header header; 502289543Scem hv_bool_uint8_t version_supported; 503250079Scarl} __packed hv_vmbus_channel_version_response; 504289648Scem 505283291Sjkimtypedef hv_vmbus_channel_msg_header hv_vmbus_channel_unload; 506283291Sjkim 507289542Scem#define HW_MACADDR_LEN 6 508289546Scem 509250079Scarl/* 510289648Scem * Fixme: Added to quiet "typeof" errors involving hv_vmbus.h when 511289648Scem * the including C file was compiled with "-std=c99". 512289348Scem */ 513289348Scem#ifndef typeof 514289348Scem#define typeof __typeof 515289348Scem#endif 516289348Scem 517289397Scem#ifndef NULL 518289396Scem#define NULL (void *)0 519289209Scem#endif 520289209Scem 521289209Scemtypedef void *hv_vmbus_handle; 522289648Scem 523289648Scem#ifndef CONTAINING_RECORD 524289272Scem#define CONTAINING_RECORD(address, type, field) ((type *)( \ 525289542Scem (uint8_t *)(address) - \ 526289209Scem (uint8_t *)(&((type *)0)->field))) 527289209Scem#endif /* CONTAINING_RECORD */ 528289540Scem 529289209Scem 530289209Scem#define container_of(ptr, type, member) ({ \ 531250079Scarl __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ 532250079Scarl (type *)( (char *)__mptr - offsetof(type,member) );}) 533250079Scarl 534289645Scemenum { 535289645Scem HV_VMBUS_IVAR_TYPE, 536289209Scem HV_VMBUS_IVAR_INSTANCE, 537289209Scem HV_VMBUS_IVAR_NODE, 538289209Scem HV_VMBUS_IVAR_DEVCTX 539250079Scarl}; 540250079Scarl 541250079Scarl#define HV_VMBUS_ACCESSOR(var, ivar, type) \ 542250079Scarl __BUS_ACCESSOR(vmbus, var, HV_VMBUS, ivar, type) 543250079Scarl 544250079ScarlHV_VMBUS_ACCESSOR(type, TYPE, const char *) 545289209ScemHV_VMBUS_ACCESSOR(devctx, DEVCTX, struct hv_device *) 546250079Scarl 547289209Scem 548289542Scem/* 549289617Scem * Common defines for Hyper-V ICs 550289617Scem */ 551250079Scarl#define HV_ICMSGTYPE_NEGOTIATE 0 552250079Scarl#define HV_ICMSGTYPE_HEARTBEAT 1 553289272Scem#define HV_ICMSGTYPE_KVPEXCHANGE 2 554289272Scem#define HV_ICMSGTYPE_SHUTDOWN 3 555250079Scarl#define HV_ICMSGTYPE_TIMESYNC 4 556289397Scem#define HV_ICMSGTYPE_VSS 5 557289542Scem 558289546Scem#define HV_ICMSGHDRFLAG_TRANSACTION 1 559289542Scem#define HV_ICMSGHDRFLAG_REQUEST 2 560289397Scem#define HV_ICMSGHDRFLAG_RESPONSE 4 561289397Scem 562289397Scemtypedef struct hv_vmbus_pipe_hdr { 563289397Scem uint32_t flags; 564289397Scem uint32_t msgsize; 565250079Scarl} __packed hv_vmbus_pipe_hdr; 566250079Scarl 567289645Scemtypedef struct hv_vmbus_ic_version { 568289645Scem uint16_t major; 569250079Scarl uint16_t minor; 570250079Scarl} __packed hv_vmbus_ic_version; 571250079Scarl 572289542Scemtypedef struct hv_vmbus_icmsg_hdr { 573289542Scem hv_vmbus_ic_version icverframe; 574289542Scem uint16_t icmsgtype; 575289539Scem hv_vmbus_ic_version icvermsg; 576289539Scem uint16_t icmsgsize; 577289539Scem uint32_t status; 578289539Scem uint8_t ictransaction_id; 579289543Scem uint8_t icflags; 580289543Scem uint8_t reserved[2]; 581289542Scem} __packed hv_vmbus_icmsg_hdr; 582289546Scem 583289539Scemtypedef struct hv_vmbus_icmsg_negotiate { 584289542Scem uint16_t icframe_vercnt; 585289539Scem uint16_t icmsg_vercnt; 586289539Scem uint32_t reserved; 587289546Scem hv_vmbus_ic_version icversion_data[1]; /* any size array */ 588289546Scem} __packed hv_vmbus_icmsg_negotiate; 589289546Scem 590289546Scemtypedef struct hv_vmbus_shutdown_msg_data { 591289546Scem uint32_t reason_code; 592289546Scem uint32_t timeout_seconds; 593289546Scem uint32_t flags; 594289546Scem uint8_t display_message[2048]; 595289546Scem} __packed hv_vmbus_shutdown_msg_data; 596289546Scem 597289546Scemtypedef struct hv_vmbus_heartbeat_msg_data { 598289546Scem uint64_t seq_num; 599289546Scem uint32_t reserved[8]; 600289546Scem} __packed hv_vmbus_heartbeat_msg_data; 601289546Scem 602289546Scemtypedef struct { 603289546Scem /* 604289546Scem * offset in bytes from the start of ring data below 605289546Scem */ 606289546Scem volatile uint32_t write_index; 607289546Scem /* 608289546Scem * offset in bytes from the start of ring data below 609289546Scem */ 610289546Scem volatile uint32_t read_index; 611289546Scem /* 612289546Scem * NOTE: The interrupt_mask field is used only for channels, but 613289546Scem * vmbus connection also uses this data structure 614289546Scem */ 615289546Scem volatile uint32_t interrupt_mask; 616289546Scem /* pad it to PAGE_SIZE so that data starts on a page */ 617289546Scem uint8_t reserved[4084]; 618289546Scem 619289546Scem /* 620289546Scem * WARNING: Ring data starts here + ring_data_start_offset 621289546Scem * !!! DO NOT place any fields below this !!! 622289546Scem */ 623289546Scem uint8_t buffer[0]; /* doubles as interrupt mask */ 624289546Scem} __packed hv_vmbus_ring_buffer; 625289546Scem 626289546Scemtypedef struct { 627289546Scem int length; 628289546Scem int offset; 629289546Scem uint64_t pfn; 630289546Scem} __packed hv_vmbus_page_buffer; 631289546Scem 632250079Scarltypedef struct { 633255272Scarl int length; 634250079Scarl int offset; 635255272Scarl uint64_t pfn_array[HV_MAX_MULTIPAGE_BUFFER_COUNT]; 636250079Scarl} __packed hv_vmbus_multipage_buffer; 637250079Scarl 638289541Scemtypedef struct { 639255272Scarl hv_vmbus_ring_buffer* ring_buffer; 640289541Scem uint32_t ring_size; /* Include the shared header */ 641255272Scarl struct mtx ring_lock; 642289209Scem uint32_t ring_data_size; /* ring_size */ 643289541Scem uint32_t ring_data_start_offset; 644255272Scarl} hv_vmbus_ring_buffer_info; 645289541Scem 646289543Scemtypedef void (*hv_vmbus_pfn_channel_callback)(void *context); 647289543Scem 648289543Scemtypedef enum { 649255272Scarl HV_CHANNEL_OFFER_STATE, 650289209Scem HV_CHANNEL_OPENING_STATE, 651289543Scem HV_CHANNEL_OPEN_STATE, 652289538Scem HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE, 653289541Scem} hv_vmbus_channel_state; 654255279Scarl 655289541Scemtypedef struct hv_vmbus_channel { 656289543Scem TAILQ_ENTRY(hv_vmbus_channel) list_entry; 657289543Scem struct hv_device* device; 658289543Scem hv_vmbus_channel_state state; 659289543Scem hv_vmbus_channel_offer_channel offer_msg; 660289397Scem /* 661289541Scem * These are based on the offer_msg.monitor_id. 662289397Scem * Save it here for easy access. 663289397Scem */ 664289538Scem uint8_t monitor_group; 665289541Scem uint8_t monitor_bit; 666289397Scem 667289541Scem uint32_t ring_buffer_gpadl_handle; 668289543Scem /* 669289543Scem * Allocated memory for ring buffer 670289543Scem */ 671250079Scarl void* ring_buffer_pages; 672289541Scem uint32_t ring_buffer_page_count; 673289209Scem /* 674255272Scarl * send to parent 675255272Scarl */ 676255272Scarl hv_vmbus_ring_buffer_info outbound; 677255272Scarl /* 678255272Scarl * receive from parent 679289541Scem */ 680289647Scem hv_vmbus_ring_buffer_info inbound; 681289647Scem 682289541Scem struct mtx inbound_lock; 683289541Scem hv_vmbus_handle control_work_queue; 684289647Scem 685289647Scem hv_vmbus_pfn_channel_callback on_channel_callback; 686289647Scem void* channel_callback_context; 687289647Scem 688289647Scem} hv_vmbus_channel; 689289647Scem 690289541Scemtypedef struct hv_device { 691289541Scem hv_guid class_id; 692255272Scarl hv_guid device_id; 693255272Scarl device_t device; 694255272Scarl hv_vmbus_channel* channel; 695255272Scarl} hv_device; 696255275Scarl 697289209Scem 698255272Scarl 699255272Scarlint hv_vmbus_channel_recv_packet( 700289209Scem hv_vmbus_channel* channel, 701289209Scem void* buffer, 702289647Scem uint32_t buffer_len, 703289209Scem uint32_t* buffer_actual_len, 704255272Scarl uint64_t* request_id); 705255272Scarl 706255272Scarlint hv_vmbus_channel_recv_packet_raw( 707255272Scarl hv_vmbus_channel* channel, 708255272Scarl void* buffer, 709255272Scarl uint32_t buffer_len, 710255276Scarl uint32_t* buffer_actual_len, 711255272Scarl uint64_t* request_id); 712289209Scem 713289209Scemint hv_vmbus_channel_open( 714250079Scarl hv_vmbus_channel* channel, 715255272Scarl uint32_t send_ring_buffer_size, 716255272Scarl uint32_t recv_ring_buffer_size, 717255276Scarl void* user_data, 718289209Scem uint32_t user_data_len, 719289209Scem hv_vmbus_pfn_channel_callback 720289209Scem pfn_on_channel_callback, 721289209Scem void* context); 722289209Scem 723289209Scemvoid hv_vmbus_channel_close(hv_vmbus_channel *channel); 724289209Scem 725289209Scemint hv_vmbus_channel_send_packet( 726289209Scem hv_vmbus_channel* channel, 727289209Scem void* buffer, 728289209Scem uint32_t buffer_len, 729289209Scem uint64_t request_id, 730289209Scem hv_vmbus_packet_type type, 731289209Scem uint32_t flags); 732289209Scem 733289209Scemint hv_vmbus_channel_send_packet_pagebuffer( 734289209Scem hv_vmbus_channel* channel, 735289209Scem hv_vmbus_page_buffer page_buffers[], 736289209Scem uint32_t page_count, 737289209Scem void* buffer, 738289209Scem uint32_t buffer_len, 739289209Scem uint64_t request_id); 740289209Scem 741289209Scemint hv_vmbus_channel_send_packet_multipagebuffer( 742289209Scem hv_vmbus_channel* channel, 743289209Scem hv_vmbus_multipage_buffer* multi_page_buffer, 744289209Scem void* buffer, 745289209Scem uint32_t buffer_len, 746255272Scarl uint64_t request_id); 747289209Scem 748289209Scemint hv_vmbus_channel_establish_gpadl( 749255272Scarl hv_vmbus_channel* channel, 750250079Scarl /* must be phys and virt contiguous */ 751289209Scem void* contig_buffer, 752289209Scem /* page-size multiple */ 753250079Scarl uint32_t size, 754289209Scem uint32_t* gpadl_handle); 755289209Scem 756289209Scemint hv_vmbus_channel_teardown_gpdal( 757289209Scem hv_vmbus_channel* channel, 758289647Scem uint32_t gpadl_handle); 759289647Scem 760289209Scem/* 761289647Scem * Work abstraction defines 762289647Scem */ 763289647Scemtypedef struct hv_work_queue { 764289647Scem struct taskqueue* queue; 765289647Scem struct proc* proc; 766289647Scem struct sema* work_sema; 767289647Scem} hv_work_queue; 768289647Scem 769289647Scemtypedef struct hv_work_item { 770289647Scem struct task work; 771289647Scem void (*callback)(void *); 772289647Scem void* context; 773289647Scem hv_work_queue* wq; 774289647Scem} hv_work_item; 775250079Scarl 776250079Scarlstruct hv_work_queue* hv_work_queue_create(char* name); 777250079Scarl 778250079Scarlvoid hv_work_queue_close(struct hv_work_queue* wq); 779250079Scarl 780250079Scarlint hv_queue_work_item( 781250079Scarl hv_work_queue* wq, 782250079Scarl void (*callback)(void *), 783250079Scarl void* context); 784289397Scem/** 785250079Scarl * @brief Get physical address from virtual 786250079Scarl */ 787250079Scarlstatic inline unsigned long 788250079Scarlhv_get_phys_addr(void *virt) 789250079Scarl{ 790250079Scarl unsigned long ret; 791250079Scarl ret = (vtophys(virt) | ((vm_offset_t) virt & PAGE_MASK)); 792250079Scarl return (ret); 793250079Scarl} 794289540Scem 795250079Scarl#endif /* __HYPERV_H__ */ 796289342Scem 797289342Scem