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. 27256352Sgrehan * 28256352Sgrehan * $FreeBSD: releng/10.3/sys/dev/hyperv/include/hyperv.h 320912 2017-07-12 08:07:55Z delphij $ 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> 49283280Swhu#include <sys/smp.h> 50250199Sgrehan#include <sys/mutex.h> 51250199Sgrehan#include <sys/bus.h> 52250199Sgrehan#include <vm/vm.h> 53250199Sgrehan#include <vm/vm_param.h> 54250199Sgrehan#include <vm/pmap.h> 55250199Sgrehan 56250199Sgrehan#include <amd64/include/xen/synch_bitops.h> 57250199Sgrehan#include <amd64/include/atomic.h> 58250199Sgrehan 59250199Sgrehantypedef uint8_t hv_bool_uint8_t; 60250199Sgrehan 61250199Sgrehan#define HV_S_OK 0x00000000 62250199Sgrehan#define HV_E_FAIL 0x80004005 63250199Sgrehan#define HV_ERROR_NOT_SUPPORTED 0x80070032 64250199Sgrehan#define HV_ERROR_MACHINE_LOCKED 0x800704F7 65250199Sgrehan 66250199Sgrehan/* 67283280Swhu * VMBUS version is 32 bit, upper 16 bit for major_number and lower 68283280Swhu * 16 bit for minor_number. 69283280Swhu * 70283280Swhu * 0.13 -- Windows Server 2008 71283280Swhu * 1.1 -- Windows 7 72283280Swhu * 2.4 -- Windows 8 73283280Swhu * 3.0 -- Windows 8.1 74250199Sgrehan */ 75283280Swhu#define HV_VMBUS_VERSION_WS2008 ((0 << 16) | (13)) 76283280Swhu#define HV_VMBUS_VERSION_WIN7 ((1 << 16) | (1)) 77283280Swhu#define HV_VMBUS_VERSION_WIN8 ((2 << 16) | (4)) 78283280Swhu#define HV_VMBUS_VERSION_WIN8_1 ((3 << 16) | (0)) 79250199Sgrehan 80283280Swhu#define HV_VMBUS_VERSION_INVALID -1 81250199Sgrehan 82283280Swhu#define HV_VMBUS_VERSION_CURRENT HV_VMBUS_VERSION_WIN8_1 83283280Swhu 84250199Sgrehan/* 85250199Sgrehan * Make maximum size of pipe payload of 16K 86250199Sgrehan */ 87250199Sgrehan 88250199Sgrehan#define HV_MAX_PIPE_DATA_PAYLOAD (sizeof(BYTE) * 16384) 89250199Sgrehan 90250199Sgrehan/* 91250199Sgrehan * Define pipe_mode values 92250199Sgrehan */ 93250199Sgrehan 94250199Sgrehan#define HV_VMBUS_PIPE_TYPE_BYTE 0x00000000 95250199Sgrehan#define HV_VMBUS_PIPE_TYPE_MESSAGE 0x00000004 96250199Sgrehan 97250199Sgrehan/* 98250199Sgrehan * The size of the user defined data buffer for non-pipe offers 99250199Sgrehan */ 100250199Sgrehan 101250199Sgrehan#define HV_MAX_USER_DEFINED_BYTES 120 102250199Sgrehan 103250199Sgrehan/* 104250199Sgrehan * The size of the user defined data buffer for pipe offers 105250199Sgrehan */ 106250199Sgrehan 107250199Sgrehan#define HV_MAX_PIPE_USER_DEFINED_BYTES 116 108250199Sgrehan 109250199Sgrehan 110285236Swhu#define HV_MAX_PAGE_BUFFER_COUNT 32 111250199Sgrehan#define HV_MAX_MULTIPAGE_BUFFER_COUNT 32 112250199Sgrehan 113250199Sgrehan#define HV_ALIGN_UP(value, align) \ 114250199Sgrehan (((value) & (align-1)) ? \ 115250199Sgrehan (((value) + (align-1)) & ~(align-1) ) : (value)) 116250199Sgrehan 117250199Sgrehan#define HV_ALIGN_DOWN(value, align) ( (value) & ~(align-1) ) 118250199Sgrehan 119250199Sgrehan#define HV_NUM_PAGES_SPANNED(addr, len) \ 120250199Sgrehan ((HV_ALIGN_UP(addr+len, PAGE_SIZE) - \ 121250199Sgrehan HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT ) 122250199Sgrehan 123250199Sgrehantypedef struct hv_guid { 124250199Sgrehan unsigned char data[16]; 125250199Sgrehan} __packed hv_guid; 126250199Sgrehan 127320912Sdelphijint snprintf_hv_guid(char *, size_t, const hv_guid *); 128320912Sdelphij 129283280Swhu#define HV_NIC_GUID \ 130283280Swhu .data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, \ 131283280Swhu 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} 132283280Swhu 133283280Swhu#define HV_IDE_GUID \ 134283280Swhu .data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, \ 135283280Swhu 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5} 136283280Swhu 137283280Swhu#define HV_SCSI_GUID \ 138283280Swhu .data = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, \ 139283280Swhu 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f} 140283280Swhu 141250199Sgrehan/* 142250199Sgrehan * At the center of the Channel Management library is 143250199Sgrehan * the Channel Offer. This struct contains the 144250199Sgrehan * fundamental information about an offer. 145250199Sgrehan */ 146250199Sgrehan 147250199Sgrehantypedef struct hv_vmbus_channel_offer { 148250199Sgrehan hv_guid interface_type; 149250199Sgrehan hv_guid interface_instance; 150250199Sgrehan uint64_t interrupt_latency_in_100ns_units; 151250199Sgrehan uint32_t interface_revision; 152250199Sgrehan uint32_t server_context_area_size; /* in bytes */ 153250199Sgrehan uint16_t channel_flags; 154250199Sgrehan uint16_t mmio_megabytes; /* in bytes * 1024 * 1024 */ 155250199Sgrehan union 156250199Sgrehan { 157250199Sgrehan /* 158250199Sgrehan * Non-pipes: The user has HV_MAX_USER_DEFINED_BYTES bytes. 159250199Sgrehan */ 160250199Sgrehan struct { 161250199Sgrehan uint8_t user_defined[HV_MAX_USER_DEFINED_BYTES]; 162250199Sgrehan } __packed standard; 163250199Sgrehan 164250199Sgrehan /* 165250199Sgrehan * Pipes: The following structure is an integrated pipe protocol, which 166250199Sgrehan * is implemented on top of standard user-defined data. pipe 167250199Sgrehan * clients have HV_MAX_PIPE_USER_DEFINED_BYTES left for their 168250199Sgrehan * own use. 169250199Sgrehan */ 170250199Sgrehan struct { 171250199Sgrehan uint32_t pipe_mode; 172250199Sgrehan uint8_t user_defined[HV_MAX_PIPE_USER_DEFINED_BYTES]; 173250199Sgrehan } __packed pipe; 174250199Sgrehan } u; 175250199Sgrehan 176283280Swhu /* 177283280Swhu * Sub_channel_index, newly added in Win8. 178283280Swhu */ 179283280Swhu uint16_t sub_channel_index; 180283280Swhu uint16_t padding; 181250199Sgrehan 182250199Sgrehan} __packed hv_vmbus_channel_offer; 183250199Sgrehan 184250199Sgrehantypedef uint32_t hv_gpadl_handle; 185250199Sgrehan 186250199Sgrehantypedef struct { 187250199Sgrehan uint16_t type; 188250199Sgrehan uint16_t data_offset8; 189250199Sgrehan uint16_t length8; 190250199Sgrehan uint16_t flags; 191250199Sgrehan uint64_t transaction_id; 192250199Sgrehan} __packed hv_vm_packet_descriptor; 193250199Sgrehan 194250199Sgrehantypedef uint32_t hv_previous_packet_offset; 195250199Sgrehan 196250199Sgrehantypedef struct { 197250199Sgrehan hv_previous_packet_offset previous_packet_start_offset; 198250199Sgrehan hv_vm_packet_descriptor descriptor; 199250199Sgrehan} __packed hv_vm_packet_header; 200250199Sgrehan 201250199Sgrehantypedef struct { 202250199Sgrehan uint32_t byte_count; 203250199Sgrehan uint32_t byte_offset; 204250199Sgrehan} __packed hv_vm_transfer_page; 205250199Sgrehan 206250199Sgrehantypedef struct { 207250199Sgrehan hv_vm_packet_descriptor d; 208250199Sgrehan uint16_t transfer_page_set_id; 209250199Sgrehan hv_bool_uint8_t sender_owns_set; 210250199Sgrehan uint8_t reserved; 211250199Sgrehan uint32_t range_count; 212250199Sgrehan hv_vm_transfer_page ranges[1]; 213250199Sgrehan} __packed hv_vm_transfer_page_packet_header; 214250199Sgrehan 215250199Sgrehantypedef struct { 216250199Sgrehan hv_vm_packet_descriptor d; 217250199Sgrehan uint32_t gpadl; 218250199Sgrehan uint32_t reserved; 219250199Sgrehan} __packed hv_vm_gpadl_packet_header; 220250199Sgrehan 221250199Sgrehantypedef struct { 222250199Sgrehan hv_vm_packet_descriptor d; 223250199Sgrehan uint32_t gpadl; 224250199Sgrehan uint16_t transfer_page_set_id; 225250199Sgrehan uint16_t reserved; 226250199Sgrehan} __packed hv_vm_add_remove_transfer_page_set; 227250199Sgrehan 228250199Sgrehan/* 229250199Sgrehan * This structure defines a range in guest 230250199Sgrehan * physical space that can be made 231250199Sgrehan * to look virtually contiguous. 232250199Sgrehan */ 233250199Sgrehan 234250199Sgrehantypedef struct { 235250199Sgrehan uint32_t byte_count; 236250199Sgrehan uint32_t byte_offset; 237250199Sgrehan uint64_t pfn_array[0]; 238250199Sgrehan} __packed hv_gpa_range; 239250199Sgrehan 240250199Sgrehan/* 241250199Sgrehan * This is the format for an Establish Gpadl packet, which contains a handle 242250199Sgrehan * by which this GPADL will be known and a set of GPA ranges associated with 243250199Sgrehan * it. This can be converted to a MDL by the guest OS. If there are multiple 244250199Sgrehan * GPA ranges, then the resulting MDL will be "chained," representing multiple 245250199Sgrehan * VA ranges. 246250199Sgrehan */ 247250199Sgrehan 248250199Sgrehantypedef struct { 249250199Sgrehan hv_vm_packet_descriptor d; 250250199Sgrehan uint32_t gpadl; 251250199Sgrehan uint32_t range_count; 252250199Sgrehan hv_gpa_range range[1]; 253250199Sgrehan} __packed hv_vm_establish_gpadl; 254250199Sgrehan 255250199Sgrehan/* 256250199Sgrehan * This is the format for a Teardown Gpadl packet, which indicates that the 257250199Sgrehan * GPADL handle in the Establish Gpadl packet will never be referenced again. 258250199Sgrehan */ 259250199Sgrehan 260250199Sgrehantypedef struct { 261250199Sgrehan hv_vm_packet_descriptor d; 262250199Sgrehan uint32_t gpadl; 263250199Sgrehan /* for alignment to a 8-byte boundary */ 264250199Sgrehan uint32_t reserved; 265250199Sgrehan} __packed hv_vm_teardown_gpadl; 266250199Sgrehan 267250199Sgrehan/* 268250199Sgrehan * This is the format for a GPA-Direct packet, which contains a set of GPA 269250199Sgrehan * ranges, in addition to commands and/or data. 270250199Sgrehan */ 271250199Sgrehan 272250199Sgrehantypedef struct { 273250199Sgrehan hv_vm_packet_descriptor d; 274250199Sgrehan uint32_t reserved; 275250199Sgrehan uint32_t range_count; 276250199Sgrehan hv_gpa_range range[1]; 277250199Sgrehan} __packed hv_vm_data_gpa_direct; 278250199Sgrehan 279250199Sgrehan/* 280250199Sgrehan * This is the format for a Additional data Packet. 281250199Sgrehan */ 282250199Sgrehantypedef struct { 283250199Sgrehan hv_vm_packet_descriptor d; 284250199Sgrehan uint64_t total_bytes; 285250199Sgrehan uint32_t byte_offset; 286250199Sgrehan uint32_t byte_count; 287250199Sgrehan uint8_t data[1]; 288250199Sgrehan} __packed hv_vm_additional_data; 289250199Sgrehan 290250199Sgrehantypedef union { 291250199Sgrehan hv_vm_packet_descriptor simple_header; 292250199Sgrehan hv_vm_transfer_page_packet_header transfer_page_header; 293250199Sgrehan hv_vm_gpadl_packet_header gpadl_header; 294250199Sgrehan hv_vm_add_remove_transfer_page_set add_remove_transfer_page_header; 295250199Sgrehan hv_vm_establish_gpadl establish_gpadl_header; 296250199Sgrehan hv_vm_teardown_gpadl teardown_gpadl_header; 297250199Sgrehan hv_vm_data_gpa_direct data_gpa_direct_header; 298250199Sgrehan} __packed hv_vm_packet_largest_possible_header; 299250199Sgrehan 300250199Sgrehantypedef enum { 301250199Sgrehan HV_VMBUS_PACKET_TYPE_INVALID = 0x0, 302250199Sgrehan HV_VMBUS_PACKET_TYPES_SYNCH = 0x1, 303250199Sgrehan HV_VMBUS_PACKET_TYPE_ADD_TRANSFER_PAGE_SET = 0x2, 304250199Sgrehan HV_VMBUS_PACKET_TYPE_REMOVE_TRANSFER_PAGE_SET = 0x3, 305250199Sgrehan HV_VMBUS_PACKET_TYPE_ESTABLISH_GPADL = 0x4, 306250199Sgrehan HV_VMBUS_PACKET_TYPE_TEAR_DOWN_GPADL = 0x5, 307250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_IN_BAND = 0x6, 308250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES = 0x7, 309250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_GPADL = 0x8, 310250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT = 0x9, 311250199Sgrehan HV_VMBUS_PACKET_TYPE_CANCEL_REQUEST = 0xa, 312250199Sgrehan HV_VMBUS_PACKET_TYPE_COMPLETION = 0xb, 313250199Sgrehan HV_VMBUS_PACKET_TYPE_DATA_USING_ADDITIONAL_PACKETS = 0xc, 314250199Sgrehan HV_VMBUS_PACKET_TYPE_ADDITIONAL_DATA = 0xd 315250199Sgrehan} hv_vmbus_packet_type; 316250199Sgrehan 317250199Sgrehan#define HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED 1 318250199Sgrehan 319250199Sgrehan/* 320250199Sgrehan * Version 1 messages 321250199Sgrehan */ 322250199Sgrehantypedef enum { 323250199Sgrehan HV_CHANNEL_MESSAGE_INVALID = 0, 324250199Sgrehan HV_CHANNEL_MESSAGE_OFFER_CHANNEL = 1, 325250199Sgrehan HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER = 2, 326250199Sgrehan HV_CHANNEL_MESSAGE_REQUEST_OFFERS = 3, 327250199Sgrehan HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED = 4, 328250199Sgrehan HV_CHANNEL_MESSAGE_OPEN_CHANNEL = 5, 329250199Sgrehan HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT = 6, 330250199Sgrehan HV_CHANNEL_MESSAGE_CLOSE_CHANNEL = 7, 331250199Sgrehan HV_CHANNEL_MESSAGEL_GPADL_HEADER = 8, 332250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_BODY = 9, 333250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_CREATED = 10, 334250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_TEARDOWN = 11, 335250199Sgrehan HV_CHANNEL_MESSAGE_GPADL_TORNDOWN = 12, 336250199Sgrehan HV_CHANNEL_MESSAGE_REL_ID_RELEASED = 13, 337250199Sgrehan HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14, 338250199Sgrehan HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15, 339250199Sgrehan HV_CHANNEL_MESSAGE_UNLOAD = 16, 340250199Sgrehan HV_CHANNEL_MESSAGE_COUNT 341250199Sgrehan} hv_vmbus_channel_msg_type; 342250199Sgrehan 343250199Sgrehantypedef struct { 344250199Sgrehan hv_vmbus_channel_msg_type message_type; 345250199Sgrehan uint32_t padding; 346250199Sgrehan} __packed hv_vmbus_channel_msg_header; 347250199Sgrehan 348250199Sgrehan/* 349250199Sgrehan * Query VMBus Version parameters 350250199Sgrehan */ 351250199Sgrehantypedef struct { 352250199Sgrehan hv_vmbus_channel_msg_header header; 353250199Sgrehan uint32_t version; 354250199Sgrehan} __packed hv_vmbus_channel_query_vmbus_version; 355250199Sgrehan 356250199Sgrehan/* 357250199Sgrehan * VMBus Version Supported parameters 358250199Sgrehan */ 359250199Sgrehantypedef struct { 360250199Sgrehan hv_vmbus_channel_msg_header header; 361250199Sgrehan hv_bool_uint8_t version_supported; 362250199Sgrehan} __packed hv_vmbus_channel_version_supported; 363250199Sgrehan 364250199Sgrehan/* 365250199Sgrehan * Channel Offer parameters 366250199Sgrehan */ 367250199Sgrehantypedef struct { 368250199Sgrehan hv_vmbus_channel_msg_header header; 369250199Sgrehan hv_vmbus_channel_offer offer; 370250199Sgrehan uint32_t child_rel_id; 371250199Sgrehan uint8_t monitor_id; 372283280Swhu /* 373283280Swhu * This field has been split into a bit field on Win7 374283280Swhu * and higher. 375283280Swhu */ 376283280Swhu uint8_t monitor_allocated:1; 377283280Swhu uint8_t reserved:7; 378283280Swhu /* 379283280Swhu * Following fields were added in win7 and higher. 380283280Swhu * Make sure to check the version before accessing these fields. 381283280Swhu * 382283280Swhu * If "is_dedicated_interrupt" is set, we must not set the 383283280Swhu * associated bit in the channel bitmap while sending the 384283280Swhu * interrupt to the host. 385283280Swhu * 386283280Swhu * connection_id is used in signaling the host. 387283280Swhu */ 388283280Swhu uint16_t is_dedicated_interrupt:1; 389283280Swhu uint16_t reserved1:15; 390283280Swhu uint32_t connection_id; 391250199Sgrehan} __packed hv_vmbus_channel_offer_channel; 392250199Sgrehan 393250199Sgrehan/* 394250199Sgrehan * Rescind Offer parameters 395250199Sgrehan */ 396250199Sgrehantypedef struct 397250199Sgrehan{ 398250199Sgrehan hv_vmbus_channel_msg_header header; 399250199Sgrehan uint32_t child_rel_id; 400250199Sgrehan} __packed hv_vmbus_channel_rescind_offer; 401250199Sgrehan 402250199Sgrehan 403250199Sgrehan/* 404250199Sgrehan * Request Offer -- no parameters, SynIC message contains the partition ID 405250199Sgrehan * 406250199Sgrehan * Set Snoop -- no parameters, SynIC message contains the partition ID 407250199Sgrehan * 408250199Sgrehan * Clear Snoop -- no parameters, SynIC message contains the partition ID 409250199Sgrehan * 410250199Sgrehan * All Offers Delivered -- no parameters, SynIC message contains the 411250199Sgrehan * partition ID 412250199Sgrehan * 413250199Sgrehan * Flush Client -- no parameters, SynIC message contains the partition ID 414250199Sgrehan */ 415250199Sgrehan 416250199Sgrehan 417250199Sgrehan/* 418250199Sgrehan * Open Channel parameters 419250199Sgrehan */ 420250199Sgrehantypedef struct 421250199Sgrehan{ 422250199Sgrehan hv_vmbus_channel_msg_header header; 423250199Sgrehan 424250199Sgrehan /* 425250199Sgrehan * Identifies the specific VMBus channel that is being opened. 426250199Sgrehan */ 427250199Sgrehan uint32_t child_rel_id; 428250199Sgrehan 429250199Sgrehan /* 430250199Sgrehan * ID making a particular open request at a channel offer unique. 431250199Sgrehan */ 432250199Sgrehan uint32_t open_id; 433250199Sgrehan 434250199Sgrehan /* 435250199Sgrehan * GPADL for the channel's ring buffer. 436250199Sgrehan */ 437250199Sgrehan hv_gpadl_handle ring_buffer_gpadl_handle; 438250199Sgrehan 439250199Sgrehan /* 440283280Swhu * Before win8, all incoming channel interrupts are only 441283280Swhu * delivered on cpu 0. Setting this value to 0 would 442283280Swhu * preserve the earlier behavior. 443250199Sgrehan */ 444283280Swhu uint32_t target_vcpu; 445250199Sgrehan 446250199Sgrehan /* 447250199Sgrehan * The upstream ring buffer begins at offset zero in the memory described 448250199Sgrehan * by ring_buffer_gpadl_handle. The downstream ring buffer follows it at 449250199Sgrehan * this offset (in pages). 450250199Sgrehan */ 451250199Sgrehan uint32_t downstream_ring_buffer_page_offset; 452250199Sgrehan 453250199Sgrehan /* 454250199Sgrehan * User-specific data to be passed along to the server endpoint. 455250199Sgrehan */ 456250199Sgrehan uint8_t user_data[HV_MAX_USER_DEFINED_BYTES]; 457250199Sgrehan 458250199Sgrehan} __packed hv_vmbus_channel_open_channel; 459250199Sgrehan 460250199Sgrehantypedef uint32_t hv_nt_status; 461250199Sgrehan 462250199Sgrehan/* 463250199Sgrehan * Open Channel Result parameters 464250199Sgrehan */ 465250199Sgrehantypedef struct 466250199Sgrehan{ 467250199Sgrehan hv_vmbus_channel_msg_header header; 468250199Sgrehan uint32_t child_rel_id; 469250199Sgrehan uint32_t open_id; 470250199Sgrehan hv_nt_status status; 471250199Sgrehan} __packed hv_vmbus_channel_open_result; 472250199Sgrehan 473250199Sgrehan/* 474250199Sgrehan * Close channel parameters 475250199Sgrehan */ 476250199Sgrehantypedef struct 477250199Sgrehan{ 478250199Sgrehan hv_vmbus_channel_msg_header header; 479250199Sgrehan uint32_t child_rel_id; 480250199Sgrehan} __packed hv_vmbus_channel_close_channel; 481250199Sgrehan 482250199Sgrehan/* 483250199Sgrehan * Channel Message GPADL 484250199Sgrehan */ 485250199Sgrehan#define HV_GPADL_TYPE_RING_BUFFER 1 486250199Sgrehan#define HV_GPADL_TYPE_SERVER_SAVE_AREA 2 487250199Sgrehan#define HV_GPADL_TYPE_TRANSACTION 8 488250199Sgrehan 489250199Sgrehan/* 490250199Sgrehan * The number of PFNs in a GPADL message is defined by the number of pages 491250199Sgrehan * that would be spanned by byte_count and byte_offset. If the implied number 492250199Sgrehan * of PFNs won't fit in this packet, there will be a follow-up packet that 493250199Sgrehan * contains more 494250199Sgrehan */ 495250199Sgrehan 496250199Sgrehantypedef struct { 497250199Sgrehan hv_vmbus_channel_msg_header header; 498250199Sgrehan uint32_t child_rel_id; 499250199Sgrehan uint32_t gpadl; 500250199Sgrehan uint16_t range_buf_len; 501250199Sgrehan uint16_t range_count; 502250199Sgrehan hv_gpa_range range[0]; 503250199Sgrehan} __packed hv_vmbus_channel_gpadl_header; 504250199Sgrehan 505250199Sgrehan/* 506250199Sgrehan * This is the follow-up packet that contains more PFNs 507250199Sgrehan */ 508250199Sgrehantypedef struct { 509250199Sgrehan hv_vmbus_channel_msg_header header; 510250199Sgrehan uint32_t message_number; 511250199Sgrehan uint32_t gpadl; 512250199Sgrehan uint64_t pfn[0]; 513250199Sgrehan} __packed hv_vmbus_channel_gpadl_body; 514250199Sgrehan 515250199Sgrehantypedef struct { 516250199Sgrehan hv_vmbus_channel_msg_header header; 517250199Sgrehan uint32_t child_rel_id; 518250199Sgrehan uint32_t gpadl; 519250199Sgrehan uint32_t creation_status; 520250199Sgrehan} __packed hv_vmbus_channel_gpadl_created; 521250199Sgrehan 522250199Sgrehantypedef struct { 523250199Sgrehan hv_vmbus_channel_msg_header header; 524250199Sgrehan uint32_t child_rel_id; 525250199Sgrehan uint32_t gpadl; 526250199Sgrehan} __packed hv_vmbus_channel_gpadl_teardown; 527250199Sgrehan 528250199Sgrehantypedef struct { 529250199Sgrehan hv_vmbus_channel_msg_header header; 530250199Sgrehan uint32_t gpadl; 531250199Sgrehan} __packed hv_vmbus_channel_gpadl_torndown; 532250199Sgrehan 533250199Sgrehantypedef struct { 534250199Sgrehan hv_vmbus_channel_msg_header header; 535250199Sgrehan uint32_t child_rel_id; 536250199Sgrehan} __packed hv_vmbus_channel_relid_released; 537250199Sgrehan 538250199Sgrehantypedef struct { 539250199Sgrehan hv_vmbus_channel_msg_header header; 540250199Sgrehan uint32_t vmbus_version_requested; 541250199Sgrehan uint32_t padding2; 542250199Sgrehan uint64_t interrupt_page; 543250199Sgrehan uint64_t monitor_page_1; 544250199Sgrehan uint64_t monitor_page_2; 545250199Sgrehan} __packed hv_vmbus_channel_initiate_contact; 546250199Sgrehan 547250199Sgrehantypedef struct { 548250199Sgrehan hv_vmbus_channel_msg_header header; 549250199Sgrehan hv_bool_uint8_t version_supported; 550250199Sgrehan} __packed hv_vmbus_channel_version_response; 551250199Sgrehan 552250199Sgrehantypedef hv_vmbus_channel_msg_header hv_vmbus_channel_unload; 553250199Sgrehan 554250199Sgrehan#define HW_MACADDR_LEN 6 555250199Sgrehan 556250199Sgrehan/* 557250199Sgrehan * Fixme: Added to quiet "typeof" errors involving hv_vmbus.h when 558250199Sgrehan * the including C file was compiled with "-std=c99". 559250199Sgrehan */ 560250199Sgrehan#ifndef typeof 561250199Sgrehan#define typeof __typeof 562250199Sgrehan#endif 563250199Sgrehan 564250199Sgrehan#ifndef NULL 565250199Sgrehan#define NULL (void *)0 566250199Sgrehan#endif 567250199Sgrehan 568250199Sgrehantypedef void *hv_vmbus_handle; 569250199Sgrehan 570250199Sgrehan#ifndef CONTAINING_RECORD 571250199Sgrehan#define CONTAINING_RECORD(address, type, field) ((type *)( \ 572250199Sgrehan (uint8_t *)(address) - \ 573250199Sgrehan (uint8_t *)(&((type *)0)->field))) 574250199Sgrehan#endif /* CONTAINING_RECORD */ 575250199Sgrehan 576250199Sgrehan 577250199Sgrehan#define container_of(ptr, type, member) ({ \ 578250199Sgrehan __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ 579250199Sgrehan (type *)( (char *)__mptr - offsetof(type,member) );}) 580250199Sgrehan 581250199Sgrehanenum { 582250199Sgrehan HV_VMBUS_IVAR_TYPE, 583250199Sgrehan HV_VMBUS_IVAR_INSTANCE, 584250199Sgrehan HV_VMBUS_IVAR_NODE, 585250199Sgrehan HV_VMBUS_IVAR_DEVCTX 586250199Sgrehan}; 587250199Sgrehan 588250199Sgrehan#define HV_VMBUS_ACCESSOR(var, ivar, type) \ 589250199Sgrehan __BUS_ACCESSOR(vmbus, var, HV_VMBUS, ivar, type) 590250199Sgrehan 591250199SgrehanHV_VMBUS_ACCESSOR(type, TYPE, const char *) 592250199SgrehanHV_VMBUS_ACCESSOR(devctx, DEVCTX, struct hv_device *) 593250199Sgrehan 594250199Sgrehan 595250199Sgrehan/* 596250199Sgrehan * Common defines for Hyper-V ICs 597250199Sgrehan */ 598250199Sgrehan#define HV_ICMSGTYPE_NEGOTIATE 0 599250199Sgrehan#define HV_ICMSGTYPE_HEARTBEAT 1 600250199Sgrehan#define HV_ICMSGTYPE_KVPEXCHANGE 2 601250199Sgrehan#define HV_ICMSGTYPE_SHUTDOWN 3 602250199Sgrehan#define HV_ICMSGTYPE_TIMESYNC 4 603250199Sgrehan#define HV_ICMSGTYPE_VSS 5 604250199Sgrehan 605250199Sgrehan#define HV_ICMSGHDRFLAG_TRANSACTION 1 606250199Sgrehan#define HV_ICMSGHDRFLAG_REQUEST 2 607250199Sgrehan#define HV_ICMSGHDRFLAG_RESPONSE 4 608250199Sgrehan 609250199Sgrehantypedef struct hv_vmbus_pipe_hdr { 610250199Sgrehan uint32_t flags; 611250199Sgrehan uint32_t msgsize; 612250199Sgrehan} __packed hv_vmbus_pipe_hdr; 613250199Sgrehan 614250199Sgrehantypedef struct hv_vmbus_ic_version { 615250199Sgrehan uint16_t major; 616250199Sgrehan uint16_t minor; 617250199Sgrehan} __packed hv_vmbus_ic_version; 618250199Sgrehan 619250199Sgrehantypedef struct hv_vmbus_icmsg_hdr { 620250199Sgrehan hv_vmbus_ic_version icverframe; 621250199Sgrehan uint16_t icmsgtype; 622250199Sgrehan hv_vmbus_ic_version icvermsg; 623250199Sgrehan uint16_t icmsgsize; 624250199Sgrehan uint32_t status; 625250199Sgrehan uint8_t ictransaction_id; 626250199Sgrehan uint8_t icflags; 627250199Sgrehan uint8_t reserved[2]; 628250199Sgrehan} __packed hv_vmbus_icmsg_hdr; 629250199Sgrehan 630250199Sgrehantypedef struct hv_vmbus_icmsg_negotiate { 631250199Sgrehan uint16_t icframe_vercnt; 632250199Sgrehan uint16_t icmsg_vercnt; 633250199Sgrehan uint32_t reserved; 634250199Sgrehan hv_vmbus_ic_version icversion_data[1]; /* any size array */ 635250199Sgrehan} __packed hv_vmbus_icmsg_negotiate; 636250199Sgrehan 637250199Sgrehantypedef struct hv_vmbus_shutdown_msg_data { 638250199Sgrehan uint32_t reason_code; 639250199Sgrehan uint32_t timeout_seconds; 640250199Sgrehan uint32_t flags; 641250199Sgrehan uint8_t display_message[2048]; 642250199Sgrehan} __packed hv_vmbus_shutdown_msg_data; 643250199Sgrehan 644250199Sgrehantypedef struct hv_vmbus_heartbeat_msg_data { 645250199Sgrehan uint64_t seq_num; 646250199Sgrehan uint32_t reserved[8]; 647250199Sgrehan} __packed hv_vmbus_heartbeat_msg_data; 648250199Sgrehan 649250199Sgrehantypedef struct { 650250199Sgrehan /* 651250199Sgrehan * offset in bytes from the start of ring data below 652250199Sgrehan */ 653250199Sgrehan volatile uint32_t write_index; 654250199Sgrehan /* 655250199Sgrehan * offset in bytes from the start of ring data below 656250199Sgrehan */ 657250199Sgrehan volatile uint32_t read_index; 658250199Sgrehan /* 659250199Sgrehan * NOTE: The interrupt_mask field is used only for channels, but 660250199Sgrehan * vmbus connection also uses this data structure 661250199Sgrehan */ 662250199Sgrehan volatile uint32_t interrupt_mask; 663250199Sgrehan /* pad it to PAGE_SIZE so that data starts on a page */ 664250199Sgrehan uint8_t reserved[4084]; 665250199Sgrehan 666250199Sgrehan /* 667250199Sgrehan * WARNING: Ring data starts here + ring_data_start_offset 668250199Sgrehan * !!! DO NOT place any fields below this !!! 669250199Sgrehan */ 670250199Sgrehan uint8_t buffer[0]; /* doubles as interrupt mask */ 671250199Sgrehan} __packed hv_vmbus_ring_buffer; 672250199Sgrehan 673250199Sgrehantypedef struct { 674250199Sgrehan int length; 675250199Sgrehan int offset; 676250199Sgrehan uint64_t pfn; 677250199Sgrehan} __packed hv_vmbus_page_buffer; 678250199Sgrehan 679250199Sgrehantypedef struct { 680250199Sgrehan int length; 681250199Sgrehan int offset; 682250199Sgrehan uint64_t pfn_array[HV_MAX_MULTIPAGE_BUFFER_COUNT]; 683250199Sgrehan} __packed hv_vmbus_multipage_buffer; 684250199Sgrehan 685250199Sgrehantypedef struct { 686250199Sgrehan hv_vmbus_ring_buffer* ring_buffer; 687250199Sgrehan uint32_t ring_size; /* Include the shared header */ 688250199Sgrehan struct mtx ring_lock; 689250199Sgrehan uint32_t ring_data_size; /* ring_size */ 690250199Sgrehan uint32_t ring_data_start_offset; 691250199Sgrehan} hv_vmbus_ring_buffer_info; 692250199Sgrehan 693250199Sgrehantypedef void (*hv_vmbus_pfn_channel_callback)(void *context); 694283280Swhutypedef void (*hv_vmbus_sc_creation_callback)(void *context); 695250199Sgrehan 696250199Sgrehantypedef enum { 697250199Sgrehan HV_CHANNEL_OFFER_STATE, 698250199Sgrehan HV_CHANNEL_OPENING_STATE, 699250199Sgrehan HV_CHANNEL_OPEN_STATE, 700283280Swhu HV_CHANNEL_OPENED_STATE, 701250199Sgrehan HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE, 702250199Sgrehan} hv_vmbus_channel_state; 703250199Sgrehan 704283280Swhu/* 705283280Swhu * Connection identifier type 706283280Swhu */ 707283280Swhutypedef union { 708283280Swhu uint32_t as_uint32_t; 709283280Swhu struct { 710283280Swhu uint32_t id:24; 711283280Swhu uint32_t reserved:8; 712283280Swhu } u; 713283280Swhu 714283280Swhu} __packed hv_vmbus_connection_id; 715283280Swhu 716283280Swhu/* 717283280Swhu * Definition of the hv_vmbus_signal_event hypercall input structure 718283280Swhu */ 719283280Swhutypedef struct { 720283280Swhu hv_vmbus_connection_id connection_id; 721283280Swhu uint16_t flag_number; 722283280Swhu uint16_t rsvd_z; 723283280Swhu} __packed hv_vmbus_input_signal_event; 724283280Swhu 725283280Swhutypedef struct { 726283280Swhu uint64_t align8; 727283280Swhu hv_vmbus_input_signal_event event; 728283280Swhu} __packed hv_vmbus_input_signal_event_buffer; 729283280Swhu 730250199Sgrehantypedef struct hv_vmbus_channel { 731250199Sgrehan TAILQ_ENTRY(hv_vmbus_channel) list_entry; 732250199Sgrehan struct hv_device* device; 733250199Sgrehan hv_vmbus_channel_state state; 734250199Sgrehan hv_vmbus_channel_offer_channel offer_msg; 735250199Sgrehan /* 736250199Sgrehan * These are based on the offer_msg.monitor_id. 737250199Sgrehan * Save it here for easy access. 738250199Sgrehan */ 739250199Sgrehan uint8_t monitor_group; 740250199Sgrehan uint8_t monitor_bit; 741250199Sgrehan 742250199Sgrehan uint32_t ring_buffer_gpadl_handle; 743250199Sgrehan /* 744250199Sgrehan * Allocated memory for ring buffer 745250199Sgrehan */ 746250199Sgrehan void* ring_buffer_pages; 747256352Sgrehan unsigned long ring_buffer_size; 748250199Sgrehan uint32_t ring_buffer_page_count; 749250199Sgrehan /* 750250199Sgrehan * send to parent 751250199Sgrehan */ 752250199Sgrehan hv_vmbus_ring_buffer_info outbound; 753250199Sgrehan /* 754250199Sgrehan * receive from parent 755250199Sgrehan */ 756250199Sgrehan hv_vmbus_ring_buffer_info inbound; 757250199Sgrehan 758250199Sgrehan struct mtx inbound_lock; 759250199Sgrehan 760250199Sgrehan hv_vmbus_pfn_channel_callback on_channel_callback; 761250199Sgrehan void* channel_callback_context; 762250199Sgrehan 763283280Swhu /* 764283280Swhu * If batched_reading is set to "true", mask the interrupt 765283280Swhu * and read until the channel is empty. 766283280Swhu * If batched_reading is set to "false", the channel is not 767283280Swhu * going to perform batched reading. 768283280Swhu * 769283280Swhu * Batched reading is enabled by default; specific 770283280Swhu * drivers that don't want this behavior can turn it off. 771283280Swhu */ 772283280Swhu boolean_t batched_reading; 773283280Swhu 774283280Swhu boolean_t is_dedicated_interrupt; 775283280Swhu 776283280Swhu /* 777283280Swhu * Used as an input param for HV_CALL_SIGNAL_EVENT hypercall. 778283280Swhu */ 779283280Swhu hv_vmbus_input_signal_event_buffer signal_event_buffer; 780283280Swhu /* 781283280Swhu * 8-bytes aligned of the buffer above 782283280Swhu */ 783283280Swhu hv_vmbus_input_signal_event *signal_event_param; 784283280Swhu 785283280Swhu /* 786283280Swhu * From Win8, this field specifies the target virtual process 787283280Swhu * on which to deliver the interupt from the host to guest. 788283280Swhu * Before Win8, all channel interrupts would only be 789283280Swhu * delivered on cpu 0. Setting this value to 0 would preserve 790283280Swhu * the earlier behavior. 791283280Swhu */ 792283280Swhu uint32_t target_vcpu; 793283280Swhu /* The corresponding CPUID in the guest */ 794283280Swhu uint32_t target_cpu; 795283280Swhu 796283280Swhu /* 797283280Swhu * Support for multi-channels. 798283280Swhu * The initial offer is considered the primary channel and this 799283280Swhu * offer message will indicate if the host supports multi-channels. 800283280Swhu * The guest is free to ask for multi-channels to be offerred and can 801283280Swhu * open these multi-channels as a normal "primary" channel. However, 802283280Swhu * all multi-channels will have the same type and instance guids as the 803283280Swhu * primary channel. Requests sent on a given channel will result in a 804283280Swhu * response on the same channel. 805283280Swhu */ 806283280Swhu 807283280Swhu /* 808283280Swhu * Multi-channel creation callback. This callback will be called in 809283280Swhu * process context when a Multi-channel offer is received from the host. 810283280Swhu * The guest can open the Multi-channel in the context of this callback. 811283280Swhu */ 812283280Swhu hv_vmbus_sc_creation_callback sc_creation_callback; 813283280Swhu 814283280Swhu struct mtx sc_lock; 815283280Swhu 816283280Swhu /* 817283280Swhu * Link list of all the multi-channels if this is a primary channel 818283280Swhu */ 819283280Swhu TAILQ_HEAD(, hv_vmbus_channel) sc_list_anchor; 820283280Swhu TAILQ_ENTRY(hv_vmbus_channel) sc_list_entry; 821283280Swhu 822283280Swhu /* 823283280Swhu * The primary channel this sub-channle belongs to. 824283280Swhu * This will be NULL for the primary channel. 825283280Swhu */ 826283280Swhu struct hv_vmbus_channel *primary_channel; 827283280Swhu /* 828283280Swhu * Support per channel state for use by vmbus drivers. 829283280Swhu */ 830283280Swhu void *per_channel_state; 831250199Sgrehan} hv_vmbus_channel; 832250199Sgrehan 833283280Swhustatic inline void 834283280Swhuhv_set_channel_read_state(hv_vmbus_channel* channel, boolean_t state) 835283280Swhu{ 836283280Swhu channel->batched_reading = state; 837283280Swhu} 838283280Swhu 839250199Sgrehantypedef struct hv_device { 840250199Sgrehan hv_guid class_id; 841250199Sgrehan hv_guid device_id; 842250199Sgrehan device_t device; 843250199Sgrehan hv_vmbus_channel* channel; 844250199Sgrehan} hv_device; 845250199Sgrehan 846250199Sgrehan 847250199Sgrehan 848250199Sgrehanint hv_vmbus_channel_recv_packet( 849250199Sgrehan hv_vmbus_channel* channel, 850250199Sgrehan void* buffer, 851250199Sgrehan uint32_t buffer_len, 852250199Sgrehan uint32_t* buffer_actual_len, 853250199Sgrehan uint64_t* request_id); 854250199Sgrehan 855250199Sgrehanint hv_vmbus_channel_recv_packet_raw( 856250199Sgrehan hv_vmbus_channel* channel, 857250199Sgrehan void* buffer, 858250199Sgrehan uint32_t buffer_len, 859250199Sgrehan uint32_t* buffer_actual_len, 860250199Sgrehan uint64_t* request_id); 861250199Sgrehan 862250199Sgrehanint hv_vmbus_channel_open( 863250199Sgrehan hv_vmbus_channel* channel, 864250199Sgrehan uint32_t send_ring_buffer_size, 865250199Sgrehan uint32_t recv_ring_buffer_size, 866250199Sgrehan void* user_data, 867250199Sgrehan uint32_t user_data_len, 868250199Sgrehan hv_vmbus_pfn_channel_callback 869250199Sgrehan pfn_on_channel_callback, 870250199Sgrehan void* context); 871250199Sgrehan 872250199Sgrehanvoid hv_vmbus_channel_close(hv_vmbus_channel *channel); 873250199Sgrehan 874250199Sgrehanint hv_vmbus_channel_send_packet( 875250199Sgrehan hv_vmbus_channel* channel, 876250199Sgrehan void* buffer, 877250199Sgrehan uint32_t buffer_len, 878250199Sgrehan uint64_t request_id, 879250199Sgrehan hv_vmbus_packet_type type, 880250199Sgrehan uint32_t flags); 881250199Sgrehan 882250199Sgrehanint hv_vmbus_channel_send_packet_pagebuffer( 883250199Sgrehan hv_vmbus_channel* channel, 884250199Sgrehan hv_vmbus_page_buffer page_buffers[], 885250199Sgrehan uint32_t page_count, 886250199Sgrehan void* buffer, 887250199Sgrehan uint32_t buffer_len, 888250199Sgrehan uint64_t request_id); 889250199Sgrehan 890250199Sgrehanint hv_vmbus_channel_send_packet_multipagebuffer( 891250199Sgrehan hv_vmbus_channel* channel, 892250199Sgrehan hv_vmbus_multipage_buffer* multi_page_buffer, 893250199Sgrehan void* buffer, 894250199Sgrehan uint32_t buffer_len, 895250199Sgrehan uint64_t request_id); 896250199Sgrehan 897250199Sgrehanint hv_vmbus_channel_establish_gpadl( 898250199Sgrehan hv_vmbus_channel* channel, 899250199Sgrehan /* must be phys and virt contiguous */ 900250199Sgrehan void* contig_buffer, 901250199Sgrehan /* page-size multiple */ 902250199Sgrehan uint32_t size, 903250199Sgrehan uint32_t* gpadl_handle); 904250199Sgrehan 905250199Sgrehanint hv_vmbus_channel_teardown_gpdal( 906250199Sgrehan hv_vmbus_channel* channel, 907250199Sgrehan uint32_t gpadl_handle); 908250199Sgrehan 909283280Swhustruct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary); 910283280Swhu 911250199Sgrehan/* 912250199Sgrehan * Work abstraction defines 913250199Sgrehan */ 914250199Sgrehantypedef struct hv_work_queue { 915250199Sgrehan struct taskqueue* queue; 916250199Sgrehan struct proc* proc; 917250199Sgrehan struct sema* work_sema; 918250199Sgrehan} hv_work_queue; 919250199Sgrehan 920250199Sgrehantypedef struct hv_work_item { 921250199Sgrehan struct task work; 922250199Sgrehan void (*callback)(void *); 923250199Sgrehan void* context; 924250199Sgrehan hv_work_queue* wq; 925250199Sgrehan} hv_work_item; 926250199Sgrehan 927250199Sgrehanstruct hv_work_queue* hv_work_queue_create(char* name); 928250199Sgrehan 929250199Sgrehanvoid hv_work_queue_close(struct hv_work_queue* wq); 930250199Sgrehan 931250199Sgrehanint hv_queue_work_item( 932250199Sgrehan hv_work_queue* wq, 933250199Sgrehan void (*callback)(void *), 934250199Sgrehan void* context); 935250199Sgrehan/** 936250199Sgrehan * @brief Get physical address from virtual 937250199Sgrehan */ 938250199Sgrehanstatic inline unsigned long 939250199Sgrehanhv_get_phys_addr(void *virt) 940250199Sgrehan{ 941250199Sgrehan unsigned long ret; 942250199Sgrehan ret = (vtophys(virt) | ((vm_offset_t) virt & PAGE_MASK)); 943250199Sgrehan return (ret); 944250199Sgrehan} 945250199Sgrehan 946272322Sdelphij 947272322Sdelphij/** 948272322Sdelphij * KVP related structures 949272322Sdelphij * 950272322Sdelphij */ 951272322Sdelphijtypedef struct hv_vmbus_service { 952272322Sdelphij hv_guid guid; /* Hyper-V GUID */ 953272322Sdelphij char *name; /* name of service */ 954272322Sdelphij boolean_t enabled; /* service enabled */ 955272322Sdelphij hv_work_queue *work_queue; /* background work queue */ 956272322Sdelphij 957272322Sdelphij /* 958272322Sdelphij * function to initialize service 959272322Sdelphij */ 960272322Sdelphij int (*init)(struct hv_vmbus_service *); 961272322Sdelphij 962272322Sdelphij /* 963272322Sdelphij * function to process Hyper-V messages 964272322Sdelphij */ 965272322Sdelphij void (*callback)(void *); 966272322Sdelphij} hv_vmbus_service; 967272322Sdelphij 968272322Sdelphijextern uint8_t* receive_buffer[]; 969272322Sdelphijextern hv_vmbus_service service_table[]; 970283280Swhuextern uint32_t hv_vmbus_protocal_version; 971272322Sdelphij 972272322Sdelphijvoid hv_kvp_callback(void *context); 973272322Sdelphijint hv_kvp_init(hv_vmbus_service *serv); 974272322Sdelphijvoid hv_kvp_deinit(void); 975272322Sdelphij 976250199Sgrehan#endif /* __HYPERV_H__ */ 977250199Sgrehan 978