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