hyperv.h revision 250199
1250199Sgrehan/*- 2250199Sgrehan * Copyright (c) 2009-2012 Microsoft Corp. 3250199Sgrehan * Copyright (c) 2012 NetApp Inc. 4250199Sgrehan * Copyright (c) 2012 Citrix Inc. 5250199Sgrehan * All rights reserved. 6250199Sgrehan * 7250199Sgrehan * Redistribution and use in source and binary forms, with or without 8250199Sgrehan * modification, are permitted provided that the following conditions 9250199Sgrehan * are met: 10250199Sgrehan * 1. Redistributions of source code must retain the above copyright 11250199Sgrehan * notice unmodified, this list of conditions, and the following 12250199Sgrehan * disclaimer. 13250199Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 14250199Sgrehan * notice, this list of conditions and the following disclaimer in the 15250199Sgrehan * documentation and/or other materials provided with the distribution. 16250199Sgrehan * 17250199Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18250199Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19250199Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20250199Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21250199Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22250199Sgrehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23250199Sgrehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24250199Sgrehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25250199Sgrehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26250199Sgrehan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27250199Sgrehan */ 28250199Sgrehan 29250199Sgrehan/** 30250199Sgrehan * HyperV definitions for messages that are sent between instances of the 31250199Sgrehan * Channel Management Library in separate partitions, or in some cases, 32250199Sgrehan * back to itself. 33250199Sgrehan */ 34250199Sgrehan 35250199Sgrehan#ifndef __HYPERV_H__ 36250199Sgrehan#define __HYPERV_H__ 37250199Sgrehan 38250199Sgrehan#include <sys/param.h> 39250199Sgrehan#include <sys/mbuf.h> 40250199Sgrehan#include <sys/queue.h> 41250199Sgrehan#include <sys/malloc.h> 42250199Sgrehan#include <sys/kthread.h> 43250199Sgrehan#include <sys/taskqueue.h> 44250199Sgrehan#include <sys/systm.h> 45250199Sgrehan#include <sys/lock.h> 46250199Sgrehan#include <sys/sema.h> 47250199Sgrehan#include <sys/mutex.h> 48250199Sgrehan#include <sys/bus.h> 49250199Sgrehan#include <vm/vm.h> 50250199Sgrehan#include <vm/vm_param.h> 51250199Sgrehan#include <vm/pmap.h> 52250199Sgrehan 53250199Sgrehan#include <amd64/include/xen/synch_bitops.h> 54250199Sgrehan#include <amd64/include/atomic.h> 55250199Sgrehan 56250199Sgrehantypedef uint8_t hv_bool_uint8_t; 57250199Sgrehan 58250199Sgrehan#define HV_S_OK 0x00000000 59250199Sgrehan#define HV_E_FAIL 0x80004005 60250199Sgrehan#define HV_ERROR_NOT_SUPPORTED 0x80070032 61250199Sgrehan#define HV_ERROR_MACHINE_LOCKED 0x800704F7 62250199Sgrehan 63250199Sgrehan/* 64250199Sgrehan * A revision number of vmbus that is used for ensuring both ends on a 65250199Sgrehan * partition are using compatible versions. 66250199Sgrehan */ 67250199Sgrehan 68250199Sgrehan#define HV_VMBUS_REVISION_NUMBER 13 69250199Sgrehan 70250199Sgrehan/* 71250199Sgrehan * Make maximum size of pipe payload of 16K 72250199Sgrehan */ 73250199Sgrehan 74250199Sgrehan#define HV_MAX_PIPE_DATA_PAYLOAD (sizeof(BYTE) * 16384) 75250199Sgrehan 76250199Sgrehan/* 77250199Sgrehan * Define pipe_mode values 78250199Sgrehan */ 79250199Sgrehan 80250199Sgrehan#define HV_VMBUS_PIPE_TYPE_BYTE 0x00000000 81250199Sgrehan#define HV_VMBUS_PIPE_TYPE_MESSAGE 0x00000004 82250199Sgrehan 83250199Sgrehan/* 84250199Sgrehan * The size of the user defined data buffer for non-pipe offers 85250199Sgrehan */ 86250199Sgrehan 87250199Sgrehan#define HV_MAX_USER_DEFINED_BYTES 120 88250199Sgrehan 89250199Sgrehan/* 90250199Sgrehan * The size of the user defined data buffer for pipe offers 91250199Sgrehan */ 92250199Sgrehan 93250199Sgrehan#define HV_MAX_PIPE_USER_DEFINED_BYTES 116 94250199Sgrehan 95250199Sgrehan 96250199Sgrehan#define HV_MAX_PAGE_BUFFER_COUNT 16 97250199Sgrehan#define HV_MAX_MULTIPAGE_BUFFER_COUNT 32 98250199Sgrehan 99250199Sgrehan#define HV_ALIGN_UP(value, align) \ 100250199Sgrehan (((value) & (align-1)) ? \ 101250199Sgrehan (((value) + (align-1)) & ~(align-1) ) : (value)) 102250199Sgrehan 103250199Sgrehan#define HV_ALIGN_DOWN(value, align) ( (value) & ~(align-1) ) 104250199Sgrehan 105250199Sgrehan#define HV_NUM_PAGES_SPANNED(addr, len) \ 106250199Sgrehan ((HV_ALIGN_UP(addr+len, PAGE_SIZE) - \ 107250199Sgrehan HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT ) 108250199Sgrehan 109250199Sgrehantypedef struct hv_guid { 110250199Sgrehan unsigned char data[16]; 111250199Sgrehan} __packed hv_guid; 112250199Sgrehan 113250199Sgrehan/* 114250199Sgrehan * At the center of the Channel Management library is 115250199Sgrehan * the Channel Offer. This struct contains the 116250199Sgrehan * fundamental information about an offer. 117250199Sgrehan */ 118250199Sgrehan 119250199Sgrehantypedef struct hv_vmbus_channel_offer { 120250199Sgrehan hv_guid interface_type; 121250199Sgrehan hv_guid interface_instance; 122250199Sgrehan uint64_t interrupt_latency_in_100ns_units; 123250199Sgrehan uint32_t interface_revision; 124250199Sgrehan uint32_t server_context_area_size; /* in bytes */ 125250199Sgrehan uint16_t channel_flags; 126250199Sgrehan uint16_t mmio_megabytes; /* in bytes * 1024 * 1024 */ 127250199Sgrehan union 128250199Sgrehan { 129250199Sgrehan /* 130250199Sgrehan * Non-pipes: The user has HV_MAX_USER_DEFINED_BYTES bytes. 131250199Sgrehan */ 132250199Sgrehan struct { 133250199Sgrehan uint8_t user_defined[HV_MAX_USER_DEFINED_BYTES]; 134250199Sgrehan } __packed standard; 135250199Sgrehan 136250199Sgrehan /* 137250199Sgrehan * Pipes: The following structure is an integrated pipe protocol, which 138250199Sgrehan * is implemented on top of standard user-defined data. pipe 139250199Sgrehan * clients have HV_MAX_PIPE_USER_DEFINED_BYTES left for their 140250199Sgrehan * own use. 141250199Sgrehan */ 142250199Sgrehan struct { 143250199Sgrehan uint32_t pipe_mode; 144250199Sgrehan uint8_t user_defined[HV_MAX_PIPE_USER_DEFINED_BYTES]; 145250199Sgrehan } __packed pipe; 146250199Sgrehan } u; 147250199Sgrehan 148250199Sgrehan uint32_t padding; 149250199Sgrehan 150250199Sgrehan} __packed hv_vmbus_channel_offer; 151250199Sgrehan 152250199Sgrehantypedef uint32_t hv_gpadl_handle; 153250199Sgrehan 154250199Sgrehantypedef struct { 155250199Sgrehan uint16_t type; 156250199Sgrehan uint16_t data_offset8; 157250199Sgrehan uint16_t length8; 158250199Sgrehan uint16_t flags; 159250199Sgrehan uint64_t transaction_id; 160250199Sgrehan} __packed hv_vm_packet_descriptor; 161250199Sgrehan 162250199Sgrehantypedef uint32_t hv_previous_packet_offset; 163250199Sgrehan 164250199Sgrehantypedef struct { 165250199Sgrehan hv_previous_packet_offset previous_packet_start_offset; 166250199Sgrehan hv_vm_packet_descriptor descriptor; 167250199Sgrehan} __packed hv_vm_packet_header; 168250199Sgrehan 169250199Sgrehantypedef struct { 170250199Sgrehan uint32_t byte_count; 171250199Sgrehan uint32_t byte_offset; 172250199Sgrehan} __packed hv_vm_transfer_page; 173250199Sgrehan 174250199Sgrehantypedef struct { 175250199Sgrehan hv_vm_packet_descriptor d; 176250199Sgrehan uint16_t transfer_page_set_id; 177250199Sgrehan hv_bool_uint8_t sender_owns_set; 178250199Sgrehan uint8_t reserved; 179250199Sgrehan uint32_t range_count; 180250199Sgrehan hv_vm_transfer_page ranges[1]; 181250199Sgrehan} __packed hv_vm_transfer_page_packet_header; 182250199Sgrehan 183250199Sgrehantypedef struct { 184250199Sgrehan hv_vm_packet_descriptor d; 185250199Sgrehan uint32_t gpadl; 186250199Sgrehan uint32_t reserved; 187250199Sgrehan} __packed hv_vm_gpadl_packet_header; 188250199Sgrehan 189250199Sgrehantypedef struct { 190250199Sgrehan hv_vm_packet_descriptor d; 191250199Sgrehan uint32_t gpadl; 192250199Sgrehan uint16_t transfer_page_set_id; 193250199Sgrehan uint16_t reserved; 194250199Sgrehan} __packed hv_vm_add_remove_transfer_page_set; 195250199Sgrehan 196250199Sgrehan/* 197250199Sgrehan * This structure defines a range in guest 198250199Sgrehan * physical space that can be made 199250199Sgrehan * to look virtually contiguous. 200250199Sgrehan */ 201250199Sgrehan 202250199Sgrehantypedef struct { 203250199Sgrehan uint32_t byte_count; 204250199Sgrehan uint32_t byte_offset; 205250199Sgrehan uint64_t pfn_array[0]; 206250199Sgrehan} __packed hv_gpa_range; 207250199Sgrehan 208250199Sgrehan/* 209250199Sgrehan * This is the format for an Establish Gpadl packet, which contains a handle 210250199Sgrehan * by which this GPADL will be known and a set of GPA ranges associated with 211250199Sgrehan * it. This can be converted to a MDL by the guest OS. If there are multiple 212250199Sgrehan * GPA ranges, then the resulting MDL will be "chained," representing multiple 213250199Sgrehan * VA ranges. 214250199Sgrehan */ 215250199Sgrehan 216250199Sgrehantypedef struct { 217250199Sgrehan hv_vm_packet_descriptor d; 218250199Sgrehan uint32_t gpadl; 219250199Sgrehan uint32_t range_count; 220250199Sgrehan hv_gpa_range range[1]; 221250199Sgrehan} __packed hv_vm_establish_gpadl; 222250199Sgrehan 223250199Sgrehan/* 224250199Sgrehan * This is the format for a Teardown Gpadl packet, which indicates that the 225250199Sgrehan * GPADL handle in the Establish Gpadl packet will never be referenced again. 226250199Sgrehan */ 227250199Sgrehan 228250199Sgrehantypedef struct { 229250199Sgrehan hv_vm_packet_descriptor d; 230250199Sgrehan uint32_t gpadl; 231250199Sgrehan /* for alignment to a 8-byte boundary */ 232250199Sgrehan uint32_t reserved; 233250199Sgrehan} __packed hv_vm_teardown_gpadl; 234250199Sgrehan 235250199Sgrehan/* 236250199Sgrehan * This is the format for a GPA-Direct packet, which contains a set of GPA 237250199Sgrehan * ranges, in addition to commands and/or data. 238250199Sgrehan */ 239250199Sgrehan 240250199Sgrehantypedef struct { 241250199Sgrehan hv_vm_packet_descriptor d; 242250199Sgrehan uint32_t reserved; 243250199Sgrehan uint32_t range_count; 244250199Sgrehan hv_gpa_range range[1]; 245250199Sgrehan} __packed hv_vm_data_gpa_direct; 246250199Sgrehan 247250199Sgrehan/* 248250199Sgrehan * This is the format for a Additional data Packet. 249250199Sgrehan */ 250250199Sgrehantypedef struct { 251250199Sgrehan hv_vm_packet_descriptor d; 252250199Sgrehan uint64_t total_bytes; 253250199Sgrehan uint32_t byte_offset; 254250199Sgrehan uint32_t byte_count; 255250199Sgrehan uint8_t data[1]; 256250199Sgrehan} __packed hv_vm_additional_data; 257250199Sgrehan 258250199Sgrehantypedef union { 259250199Sgrehan hv_vm_packet_descriptor simple_header; 260250199Sgrehan hv_vm_transfer_page_packet_header transfer_page_header; 261250199Sgrehan hv_vm_gpadl_packet_header gpadl_header; 262250199Sgrehan hv_vm_add_remove_transfer_page_set add_remove_transfer_page_header; 263250199Sgrehan hv_vm_establish_gpadl establish_gpadl_header; 264250199Sgrehan hv_vm_teardown_gpadl teardown_gpadl_header; 265250199Sgrehan hv_vm_data_gpa_direct data_gpa_direct_header; 266250199Sgrehan} __packed hv_vm_packet_largest_possible_header; 267250199Sgrehan 268250199Sgrehantypedef enum { 269250199Sgrehan HV_VMBUS_PACKET_TYPE_INVALID = 0x0, 270250199Sgrehan HV_VMBUS_PACKET_TYPES_SYNCH = 0x1, 271250199Sgrehan HV_VMBUS_PACKET_TYPE_ADD_TRANSFER_PAGE_SET = 0x2, 272250199Sgrehan HV_VMBUS_PACKET_TYPE_REMOVE_TRANSFER_PAGE_SET = 0x3, 273250199Sgrehan HV_VMBUS_PACKET_TYPE_ESTABLISH_GPADL = 0x4, 274250199Sgrehan HV_VMBUS_PACKET_TYPE_TEAR_DOWN_GPADL = 0x5, 275250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_IN_BAND = 0x6, 276250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES = 0x7, 277250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_GPADL = 0x8, 278250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT = 0x9, 279250199Sgrehan HV_VMBUS_PACKET_TYPE_CANCEL_REQUEST = 0xa, 280250199Sgrehan HV_VMBUS_PACKET_TYPE_COMPLETION = 0xb, 281250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_ADDITIONAL_PACKETS = 0xc, 282250199Sgrehan HV_VMBUS_PACKET_TYPE_ADDITIONAL_DATA = 0xd 283250199Sgrehan} hv_vmbus_packet_type; 284250199Sgrehan 285250199Sgrehan#define HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED 1 286250199Sgrehan 287250199Sgrehan/* 288250199Sgrehan * Version 1 messages 289250199Sgrehan */ 290250199Sgrehantypedef enum { 291250199Sgrehan HV_CHANNEL_MESSAGE_INVALID = 0, 292250199Sgrehan HV_CHANNEL_MESSAGE_OFFER_CHANNEL = 1, 293250199Sgrehan HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER = 2, 294250199Sgrehan HV_CHANNEL_MESSAGE_REQUEST_OFFERS = 3, 295250199Sgrehan HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED = 4, 296250199Sgrehan HV_CHANNEL_MESSAGE_OPEN_CHANNEL = 5, 297250199Sgrehan HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT = 6, 298250199Sgrehan HV_CHANNEL_MESSAGE_CLOSE_CHANNEL = 7, 299250199Sgrehan HV_CHANNEL_MESSAGEL_GPADL_HEADER = 8, 300250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_BODY = 9, 301250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_CREATED = 10, 302250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_TEARDOWN = 11, 303250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_TORNDOWN = 12, 304250199Sgrehan HV_CHANNEL_MESSAGE_REL_ID_RELEASED = 13, 305250199Sgrehan HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14, 306250199Sgrehan HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15, 307250199Sgrehan HV_CHANNEL_MESSAGE_UNLOAD = 16, 308250199Sgrehan 309250199Sgrehan#ifdef HV_VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD 310250199Sgrehan HV_CHANNEL_MESSAGE_VIEW_RANGE_ADD = 17, 311250199Sgrehan HV_CHANNEL_MESSAGE_VIEW_RANGE_REMOVE = 18, 312250199Sgrehan#endif 313250199Sgrehan HV_CHANNEL_MESSAGE_COUNT 314250199Sgrehan} hv_vmbus_channel_msg_type; 315250199Sgrehan 316250199Sgrehantypedef struct { 317250199Sgrehan hv_vmbus_channel_msg_type message_type; 318250199Sgrehan uint32_t padding; 319250199Sgrehan} __packed hv_vmbus_channel_msg_header; 320250199Sgrehan 321250199Sgrehan/* 322250199Sgrehan * Query VMBus Version parameters 323250199Sgrehan */ 324250199Sgrehantypedef struct { 325250199Sgrehan hv_vmbus_channel_msg_header header; 326250199Sgrehan uint32_t version; 327250199Sgrehan} __packed hv_vmbus_channel_query_vmbus_version; 328250199Sgrehan 329250199Sgrehan/* 330250199Sgrehan * VMBus Version Supported parameters 331250199Sgrehan */ 332250199Sgrehantypedef struct { 333250199Sgrehan hv_vmbus_channel_msg_header header; 334250199Sgrehan hv_bool_uint8_t version_supported; 335250199Sgrehan} __packed hv_vmbus_channel_version_supported; 336250199Sgrehan 337250199Sgrehan/* 338250199Sgrehan * Channel Offer parameters 339250199Sgrehan */ 340250199Sgrehantypedef struct { 341250199Sgrehan hv_vmbus_channel_msg_header header; 342250199Sgrehan hv_vmbus_channel_offer offer; 343250199Sgrehan uint32_t child_rel_id; 344250199Sgrehan uint8_t monitor_id; 345250199Sgrehan hv_bool_uint8_t monitor_allocated; 346250199Sgrehan} __packed hv_vmbus_channel_offer_channel; 347250199Sgrehan 348250199Sgrehan/* 349250199Sgrehan * Rescind Offer parameters 350250199Sgrehan */ 351250199Sgrehantypedef struct 352250199Sgrehan{ 353250199Sgrehan hv_vmbus_channel_msg_header header; 354250199Sgrehan uint32_t child_rel_id; 355250199Sgrehan} __packed hv_vmbus_channel_rescind_offer; 356250199Sgrehan 357250199Sgrehan 358250199Sgrehan/* 359250199Sgrehan * Request Offer -- no parameters, SynIC message contains the partition ID 360250199Sgrehan * 361250199Sgrehan * Set Snoop -- no parameters, SynIC message contains the partition ID 362250199Sgrehan * 363250199Sgrehan * Clear Snoop -- no parameters, SynIC message contains the partition ID 364250199Sgrehan * 365250199Sgrehan * All Offers Delivered -- no parameters, SynIC message contains the 366250199Sgrehan * partition ID 367250199Sgrehan * 368250199Sgrehan * Flush Client -- no parameters, SynIC message contains the partition ID 369250199Sgrehan */ 370250199Sgrehan 371250199Sgrehan 372250199Sgrehan/* 373250199Sgrehan * Open Channel parameters 374250199Sgrehan */ 375250199Sgrehantypedef struct 376250199Sgrehan{ 377250199Sgrehan hv_vmbus_channel_msg_header header; 378250199Sgrehan 379250199Sgrehan /* 380250199Sgrehan * Identifies the specific VMBus channel that is being opened. 381250199Sgrehan */ 382250199Sgrehan uint32_t child_rel_id; 383250199Sgrehan 384250199Sgrehan /* 385250199Sgrehan * ID making a particular open request at a channel offer unique. 386250199Sgrehan */ 387250199Sgrehan uint32_t open_id; 388250199Sgrehan 389250199Sgrehan /* 390250199Sgrehan * GPADL for the channel's ring buffer. 391250199Sgrehan */ 392250199Sgrehan hv_gpadl_handle ring_buffer_gpadl_handle; 393250199Sgrehan 394250199Sgrehan /* 395250199Sgrehan * GPADL for the channel's server context save area. 396250199Sgrehan */ 397250199Sgrehan hv_gpadl_handle server_context_area_gpadl_handle; 398250199Sgrehan 399250199Sgrehan /* 400250199Sgrehan * The upstream ring buffer begins at offset zero in the memory described 401250199Sgrehan * by ring_buffer_gpadl_handle. The downstream ring buffer follows it at 402250199Sgrehan * this offset (in pages). 403250199Sgrehan */ 404250199Sgrehan uint32_t downstream_ring_buffer_page_offset; 405250199Sgrehan 406250199Sgrehan /* 407250199Sgrehan * User-specific data to be passed along to the server endpoint. 408250199Sgrehan */ 409250199Sgrehan uint8_t user_data[HV_MAX_USER_DEFINED_BYTES]; 410250199Sgrehan 411250199Sgrehan} __packed hv_vmbus_channel_open_channel; 412250199Sgrehan 413250199Sgrehantypedef uint32_t hv_nt_status; 414250199Sgrehan 415250199Sgrehan/* 416250199Sgrehan * Open Channel Result parameters 417250199Sgrehan */ 418250199Sgrehantypedef struct 419250199Sgrehan{ 420250199Sgrehan hv_vmbus_channel_msg_header header; 421250199Sgrehan uint32_t child_rel_id; 422250199Sgrehan uint32_t open_id; 423250199Sgrehan hv_nt_status status; 424250199Sgrehan} __packed hv_vmbus_channel_open_result; 425250199Sgrehan 426250199Sgrehan/* 427250199Sgrehan * Close channel parameters 428250199Sgrehan */ 429250199Sgrehantypedef struct 430250199Sgrehan{ 431250199Sgrehan hv_vmbus_channel_msg_header header; 432250199Sgrehan uint32_t child_rel_id; 433250199Sgrehan} __packed hv_vmbus_channel_close_channel; 434250199Sgrehan 435250199Sgrehan/* 436250199Sgrehan * Channel Message GPADL 437250199Sgrehan */ 438250199Sgrehan#define HV_GPADL_TYPE_RING_BUFFER 1 439250199Sgrehan#define HV_GPADL_TYPE_SERVER_SAVE_AREA 2 440250199Sgrehan#define HV_GPADL_TYPE_TRANSACTION 8 441250199Sgrehan 442250199Sgrehan/* 443250199Sgrehan * The number of PFNs in a GPADL message is defined by the number of pages 444250199Sgrehan * that would be spanned by byte_count and byte_offset. If the implied number 445250199Sgrehan * of PFNs won't fit in this packet, there will be a follow-up packet that 446250199Sgrehan * contains more 447250199Sgrehan */ 448250199Sgrehan 449250199Sgrehantypedef struct { 450250199Sgrehan hv_vmbus_channel_msg_header header; 451250199Sgrehan uint32_t child_rel_id; 452250199Sgrehan uint32_t gpadl; 453250199Sgrehan uint16_t range_buf_len; 454250199Sgrehan uint16_t range_count; 455250199Sgrehan hv_gpa_range range[0]; 456250199Sgrehan} __packed hv_vmbus_channel_gpadl_header; 457250199Sgrehan 458250199Sgrehan/* 459250199Sgrehan * This is the follow-up packet that contains more PFNs 460250199Sgrehan */ 461250199Sgrehantypedef struct { 462250199Sgrehan hv_vmbus_channel_msg_header header; 463250199Sgrehan uint32_t message_number; 464250199Sgrehan uint32_t gpadl; 465250199Sgrehan uint64_t pfn[0]; 466250199Sgrehan} __packed hv_vmbus_channel_gpadl_body; 467250199Sgrehan 468250199Sgrehantypedef struct { 469250199Sgrehan hv_vmbus_channel_msg_header header; 470250199Sgrehan uint32_t child_rel_id; 471250199Sgrehan uint32_t gpadl; 472250199Sgrehan uint32_t creation_status; 473250199Sgrehan} __packed hv_vmbus_channel_gpadl_created; 474250199Sgrehan 475250199Sgrehantypedef struct { 476250199Sgrehan hv_vmbus_channel_msg_header header; 477250199Sgrehan uint32_t child_rel_id; 478250199Sgrehan uint32_t gpadl; 479250199Sgrehan} __packed hv_vmbus_channel_gpadl_teardown; 480250199Sgrehan 481250199Sgrehantypedef struct { 482250199Sgrehan hv_vmbus_channel_msg_header header; 483250199Sgrehan uint32_t gpadl; 484250199Sgrehan} __packed hv_vmbus_channel_gpadl_torndown; 485250199Sgrehan 486250199Sgrehantypedef struct { 487250199Sgrehan hv_vmbus_channel_msg_header header; 488250199Sgrehan uint32_t child_rel_id; 489250199Sgrehan} __packed hv_vmbus_channel_relid_released; 490250199Sgrehan 491250199Sgrehantypedef struct { 492250199Sgrehan hv_vmbus_channel_msg_header header; 493250199Sgrehan uint32_t vmbus_version_requested; 494250199Sgrehan uint32_t padding2; 495250199Sgrehan uint64_t interrupt_page; 496250199Sgrehan uint64_t monitor_page_1; 497250199Sgrehan uint64_t monitor_page_2; 498250199Sgrehan} __packed hv_vmbus_channel_initiate_contact; 499250199Sgrehan 500250199Sgrehantypedef struct { 501250199Sgrehan hv_vmbus_channel_msg_header header; 502250199Sgrehan hv_bool_uint8_t version_supported; 503250199Sgrehan} __packed hv_vmbus_channel_version_response; 504250199Sgrehan 505250199Sgrehantypedef hv_vmbus_channel_msg_header hv_vmbus_channel_unload; 506250199Sgrehan 507250199Sgrehan#define HW_MACADDR_LEN 6 508250199Sgrehan 509250199Sgrehan/* 510250199Sgrehan * Fixme: Added to quiet "typeof" errors involving hv_vmbus.h when 511250199Sgrehan * the including C file was compiled with "-std=c99". 512250199Sgrehan */ 513250199Sgrehan#ifndef typeof 514250199Sgrehan#define typeof __typeof 515250199Sgrehan#endif 516250199Sgrehan 517250199Sgrehan#ifndef NULL 518250199Sgrehan#define NULL (void *)0 519250199Sgrehan#endif 520250199Sgrehan 521250199Sgrehantypedef void *hv_vmbus_handle; 522250199Sgrehan 523250199Sgrehan#ifndef CONTAINING_RECORD 524250199Sgrehan#define CONTAINING_RECORD(address, type, field) ((type *)( \ 525250199Sgrehan (uint8_t *)(address) - \ 526250199Sgrehan (uint8_t *)(&((type *)0)->field))) 527250199Sgrehan#endif /* CONTAINING_RECORD */ 528250199Sgrehan 529250199Sgrehan 530250199Sgrehan#define container_of(ptr, type, member) ({ \ 531250199Sgrehan __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ 532250199Sgrehan (type *)( (char *)__mptr - offsetof(type,member) );}) 533250199Sgrehan 534250199Sgrehanenum { 535250199Sgrehan HV_VMBUS_IVAR_TYPE, 536250199Sgrehan HV_VMBUS_IVAR_INSTANCE, 537250199Sgrehan HV_VMBUS_IVAR_NODE, 538250199Sgrehan HV_VMBUS_IVAR_DEVCTX 539250199Sgrehan}; 540250199Sgrehan 541250199Sgrehan#define HV_VMBUS_ACCESSOR(var, ivar, type) \ 542250199Sgrehan __BUS_ACCESSOR(vmbus, var, HV_VMBUS, ivar, type) 543250199Sgrehan 544250199SgrehanHV_VMBUS_ACCESSOR(type, TYPE, const char *) 545250199SgrehanHV_VMBUS_ACCESSOR(devctx, DEVCTX, struct hv_device *) 546250199Sgrehan 547250199Sgrehan 548250199Sgrehan/* 549250199Sgrehan * Common defines for Hyper-V ICs 550250199Sgrehan */ 551250199Sgrehan#define HV_ICMSGTYPE_NEGOTIATE 0 552250199Sgrehan#define HV_ICMSGTYPE_HEARTBEAT 1 553250199Sgrehan#define HV_ICMSGTYPE_KVPEXCHANGE 2 554250199Sgrehan#define HV_ICMSGTYPE_SHUTDOWN 3 555250199Sgrehan#define HV_ICMSGTYPE_TIMESYNC 4 556250199Sgrehan#define HV_ICMSGTYPE_VSS 5 557250199Sgrehan 558250199Sgrehan#define HV_ICMSGHDRFLAG_TRANSACTION 1 559250199Sgrehan#define HV_ICMSGHDRFLAG_REQUEST 2 560250199Sgrehan#define HV_ICMSGHDRFLAG_RESPONSE 4 561250199Sgrehan 562250199Sgrehantypedef struct hv_vmbus_pipe_hdr { 563250199Sgrehan uint32_t flags; 564250199Sgrehan uint32_t msgsize; 565250199Sgrehan} __packed hv_vmbus_pipe_hdr; 566250199Sgrehan 567250199Sgrehantypedef struct hv_vmbus_ic_version { 568250199Sgrehan uint16_t major; 569250199Sgrehan uint16_t minor; 570250199Sgrehan} __packed hv_vmbus_ic_version; 571250199Sgrehan 572250199Sgrehantypedef struct hv_vmbus_icmsg_hdr { 573250199Sgrehan hv_vmbus_ic_version icverframe; 574250199Sgrehan uint16_t icmsgtype; 575250199Sgrehan hv_vmbus_ic_version icvermsg; 576250199Sgrehan uint16_t icmsgsize; 577250199Sgrehan uint32_t status; 578250199Sgrehan uint8_t ictransaction_id; 579250199Sgrehan uint8_t icflags; 580250199Sgrehan uint8_t reserved[2]; 581250199Sgrehan} __packed hv_vmbus_icmsg_hdr; 582250199Sgrehan 583250199Sgrehantypedef struct hv_vmbus_icmsg_negotiate { 584250199Sgrehan uint16_t icframe_vercnt; 585250199Sgrehan uint16_t icmsg_vercnt; 586250199Sgrehan uint32_t reserved; 587250199Sgrehan hv_vmbus_ic_version icversion_data[1]; /* any size array */ 588250199Sgrehan} __packed hv_vmbus_icmsg_negotiate; 589250199Sgrehan 590250199Sgrehantypedef struct hv_vmbus_shutdown_msg_data { 591250199Sgrehan uint32_t reason_code; 592250199Sgrehan uint32_t timeout_seconds; 593250199Sgrehan uint32_t flags; 594250199Sgrehan uint8_t display_message[2048]; 595250199Sgrehan} __packed hv_vmbus_shutdown_msg_data; 596250199Sgrehan 597250199Sgrehantypedef struct hv_vmbus_heartbeat_msg_data { 598250199Sgrehan uint64_t seq_num; 599250199Sgrehan uint32_t reserved[8]; 600250199Sgrehan} __packed hv_vmbus_heartbeat_msg_data; 601250199Sgrehan 602250199Sgrehantypedef struct { 603250199Sgrehan /* 604250199Sgrehan * offset in bytes from the start of ring data below 605250199Sgrehan */ 606250199Sgrehan volatile uint32_t write_index; 607250199Sgrehan /* 608250199Sgrehan * offset in bytes from the start of ring data below 609250199Sgrehan */ 610250199Sgrehan volatile uint32_t read_index; 611250199Sgrehan /* 612250199Sgrehan * NOTE: The interrupt_mask field is used only for channels, but 613250199Sgrehan * vmbus connection also uses this data structure 614250199Sgrehan */ 615250199Sgrehan volatile uint32_t interrupt_mask; 616250199Sgrehan /* pad it to PAGE_SIZE so that data starts on a page */ 617250199Sgrehan uint8_t reserved[4084]; 618250199Sgrehan 619250199Sgrehan /* 620250199Sgrehan * WARNING: Ring data starts here + ring_data_start_offset 621250199Sgrehan * !!! DO NOT place any fields below this !!! 622250199Sgrehan */ 623250199Sgrehan uint8_t buffer[0]; /* doubles as interrupt mask */ 624250199Sgrehan} __packed hv_vmbus_ring_buffer; 625250199Sgrehan 626250199Sgrehantypedef struct { 627250199Sgrehan int length; 628250199Sgrehan int offset; 629250199Sgrehan uint64_t pfn; 630250199Sgrehan} __packed hv_vmbus_page_buffer; 631250199Sgrehan 632250199Sgrehantypedef struct { 633250199Sgrehan int length; 634250199Sgrehan int offset; 635250199Sgrehan uint64_t pfn_array[HV_MAX_MULTIPAGE_BUFFER_COUNT]; 636250199Sgrehan} __packed hv_vmbus_multipage_buffer; 637250199Sgrehan 638250199Sgrehantypedef struct { 639250199Sgrehan hv_vmbus_ring_buffer* ring_buffer; 640250199Sgrehan uint32_t ring_size; /* Include the shared header */ 641250199Sgrehan struct mtx ring_lock; 642250199Sgrehan uint32_t ring_data_size; /* ring_size */ 643250199Sgrehan uint32_t ring_data_start_offset; 644250199Sgrehan} hv_vmbus_ring_buffer_info; 645250199Sgrehan 646250199Sgrehantypedef void (*hv_vmbus_pfn_channel_callback)(void *context); 647250199Sgrehan 648250199Sgrehantypedef enum { 649250199Sgrehan HV_CHANNEL_OFFER_STATE, 650250199Sgrehan HV_CHANNEL_OPENING_STATE, 651250199Sgrehan HV_CHANNEL_OPEN_STATE, 652250199Sgrehan HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE, 653250199Sgrehan} hv_vmbus_channel_state; 654250199Sgrehan 655250199Sgrehantypedef struct hv_vmbus_channel { 656250199Sgrehan TAILQ_ENTRY(hv_vmbus_channel) list_entry; 657250199Sgrehan struct hv_device* device; 658250199Sgrehan hv_vmbus_channel_state state; 659250199Sgrehan hv_vmbus_channel_offer_channel offer_msg; 660250199Sgrehan /* 661250199Sgrehan * These are based on the offer_msg.monitor_id. 662250199Sgrehan * Save it here for easy access. 663250199Sgrehan */ 664250199Sgrehan uint8_t monitor_group; 665250199Sgrehan uint8_t monitor_bit; 666250199Sgrehan 667250199Sgrehan uint32_t ring_buffer_gpadl_handle; 668250199Sgrehan /* 669250199Sgrehan * Allocated memory for ring buffer 670250199Sgrehan */ 671250199Sgrehan void* ring_buffer_pages; 672250199Sgrehan uint32_t ring_buffer_page_count; 673250199Sgrehan /* 674250199Sgrehan * send to parent 675250199Sgrehan */ 676250199Sgrehan hv_vmbus_ring_buffer_info outbound; 677250199Sgrehan /* 678250199Sgrehan * receive from parent 679250199Sgrehan */ 680250199Sgrehan hv_vmbus_ring_buffer_info inbound; 681250199Sgrehan 682250199Sgrehan struct mtx inbound_lock; 683250199Sgrehan hv_vmbus_handle control_work_queue; 684250199Sgrehan 685250199Sgrehan hv_vmbus_pfn_channel_callback on_channel_callback; 686250199Sgrehan void* channel_callback_context; 687250199Sgrehan 688250199Sgrehan} hv_vmbus_channel; 689250199Sgrehan 690250199Sgrehantypedef struct hv_device { 691250199Sgrehan hv_guid class_id; 692250199Sgrehan hv_guid device_id; 693250199Sgrehan device_t device; 694250199Sgrehan hv_vmbus_channel* channel; 695250199Sgrehan} hv_device; 696250199Sgrehan 697250199Sgrehan 698250199Sgrehan 699250199Sgrehanint hv_vmbus_channel_recv_packet( 700250199Sgrehan hv_vmbus_channel* channel, 701250199Sgrehan void* buffer, 702250199Sgrehan uint32_t buffer_len, 703250199Sgrehan uint32_t* buffer_actual_len, 704250199Sgrehan uint64_t* request_id); 705250199Sgrehan 706250199Sgrehanint hv_vmbus_channel_recv_packet_raw( 707250199Sgrehan hv_vmbus_channel* channel, 708250199Sgrehan void* buffer, 709250199Sgrehan uint32_t buffer_len, 710250199Sgrehan uint32_t* buffer_actual_len, 711250199Sgrehan uint64_t* request_id); 712250199Sgrehan 713250199Sgrehanint hv_vmbus_channel_open( 714250199Sgrehan hv_vmbus_channel* channel, 715250199Sgrehan uint32_t send_ring_buffer_size, 716250199Sgrehan uint32_t recv_ring_buffer_size, 717250199Sgrehan void* user_data, 718250199Sgrehan uint32_t user_data_len, 719250199Sgrehan hv_vmbus_pfn_channel_callback 720250199Sgrehan pfn_on_channel_callback, 721250199Sgrehan void* context); 722250199Sgrehan 723250199Sgrehanvoid hv_vmbus_channel_close(hv_vmbus_channel *channel); 724250199Sgrehan 725250199Sgrehanint hv_vmbus_channel_send_packet( 726250199Sgrehan hv_vmbus_channel* channel, 727250199Sgrehan void* buffer, 728250199Sgrehan uint32_t buffer_len, 729250199Sgrehan uint64_t request_id, 730250199Sgrehan hv_vmbus_packet_type type, 731250199Sgrehan uint32_t flags); 732250199Sgrehan 733250199Sgrehanint hv_vmbus_channel_send_packet_pagebuffer( 734250199Sgrehan hv_vmbus_channel* channel, 735250199Sgrehan hv_vmbus_page_buffer page_buffers[], 736250199Sgrehan uint32_t page_count, 737250199Sgrehan void* buffer, 738250199Sgrehan uint32_t buffer_len, 739250199Sgrehan uint64_t request_id); 740250199Sgrehan 741250199Sgrehanint hv_vmbus_channel_send_packet_multipagebuffer( 742250199Sgrehan hv_vmbus_channel* channel, 743250199Sgrehan hv_vmbus_multipage_buffer* multi_page_buffer, 744250199Sgrehan void* buffer, 745250199Sgrehan uint32_t buffer_len, 746250199Sgrehan uint64_t request_id); 747250199Sgrehan 748250199Sgrehanint hv_vmbus_channel_establish_gpadl( 749250199Sgrehan hv_vmbus_channel* channel, 750250199Sgrehan /* must be phys and virt contiguous */ 751250199Sgrehan void* contig_buffer, 752250199Sgrehan /* page-size multiple */ 753250199Sgrehan uint32_t size, 754250199Sgrehan uint32_t* gpadl_handle); 755250199Sgrehan 756250199Sgrehanint hv_vmbus_channel_teardown_gpdal( 757250199Sgrehan hv_vmbus_channel* channel, 758250199Sgrehan uint32_t gpadl_handle); 759250199Sgrehan 760250199Sgrehan/* 761250199Sgrehan * Work abstraction defines 762250199Sgrehan */ 763250199Sgrehantypedef struct hv_work_queue { 764250199Sgrehan struct taskqueue* queue; 765250199Sgrehan struct proc* proc; 766250199Sgrehan struct sema* work_sema; 767250199Sgrehan} hv_work_queue; 768250199Sgrehan 769250199Sgrehantypedef struct hv_work_item { 770250199Sgrehan struct task work; 771250199Sgrehan void (*callback)(void *); 772250199Sgrehan void* context; 773250199Sgrehan hv_work_queue* wq; 774250199Sgrehan} hv_work_item; 775250199Sgrehan 776250199Sgrehanstruct hv_work_queue* hv_work_queue_create(char* name); 777250199Sgrehan 778250199Sgrehanvoid hv_work_queue_close(struct hv_work_queue* wq); 779250199Sgrehan 780250199Sgrehanint hv_queue_work_item( 781250199Sgrehan hv_work_queue* wq, 782250199Sgrehan void (*callback)(void *), 783250199Sgrehan void* context); 784250199Sgrehan/** 785250199Sgrehan * @brief Get physical address from virtual 786250199Sgrehan */ 787250199Sgrehanstatic inline unsigned long 788250199Sgrehanhv_get_phys_addr(void *virt) 789250199Sgrehan{ 790250199Sgrehan unsigned long ret; 791250199Sgrehan ret = (vtophys(virt) | ((vm_offset_t) virt & PAGE_MASK)); 792250199Sgrehan return (ret); 793250199Sgrehan} 794250199Sgrehan 795250199Sgrehan#endif /* __HYPERV_H__ */ 796250199Sgrehan 797