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. 27256276Sdim * 28256276Sdim * $FreeBSD: releng/10.3/sys/dev/hyperv/vmbus/hv_vmbus_priv.h 303984 2016-08-12 04:01:16Z glebius $ 29250199Sgrehan */ 30250199Sgrehan 31250199Sgrehan#ifndef __HYPERV_PRIV_H__ 32250199Sgrehan#define __HYPERV_PRIV_H__ 33250199Sgrehan 34250199Sgrehan#include <sys/param.h> 35250199Sgrehan#include <sys/lock.h> 36250199Sgrehan#include <sys/mutex.h> 37250199Sgrehan#include <sys/sema.h> 38250199Sgrehan 39250199Sgrehan#include <dev/hyperv/include/hyperv.h> 40250199Sgrehan 41250199Sgrehan 42250199Sgrehan/* 43250199Sgrehan * Status codes for hypervisor operations. 44250199Sgrehan */ 45250199Sgrehan 46250199Sgrehantypedef uint16_t hv_vmbus_status; 47250199Sgrehan 48250199Sgrehan#define HV_MESSAGE_SIZE (256) 49250199Sgrehan#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) 50250199Sgrehan#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) 51250199Sgrehan#define HV_ANY_VP (0xFFFFFFFF) 52250199Sgrehan 53250199Sgrehan/* 54250199Sgrehan * Synthetic interrupt controller flag constants. 55250199Sgrehan */ 56250199Sgrehan 57250199Sgrehan#define HV_EVENT_FLAGS_COUNT (256 * 8) 58250199Sgrehan#define HV_EVENT_FLAGS_BYTE_COUNT (256) 59250199Sgrehan#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(uint32_t)) 60250199Sgrehan 61295948Ssephe/** 62295948Ssephe * max channel count <== event_flags_dword_count * bit_of_dword 63295948Ssephe */ 64295948Ssephe#define HV_CHANNEL_DWORD_LEN (32) 65295948Ssephe#define HV_CHANNEL_MAX_COUNT \ 66295948Ssephe ((HV_EVENT_FLAGS_DWORD_COUNT) * HV_CHANNEL_DWORD_LEN) 67250199Sgrehan/* 68250199Sgrehan * MessageId: HV_STATUS_INSUFFICIENT_BUFFERS 69250199Sgrehan * MessageText: 70250199Sgrehan * You did not supply enough message buffers to send a message. 71250199Sgrehan */ 72250199Sgrehan 73303984Sglebius#define HV_STATUS_SUCCESS ((uint16_t)0) 74250199Sgrehan#define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013) 75250199Sgrehan 76250199Sgrehantypedef void (*hv_vmbus_channel_callback)(void *context); 77250199Sgrehan 78250199Sgrehantypedef struct { 79250199Sgrehan void* data; 80250199Sgrehan uint32_t length; 81250199Sgrehan} hv_vmbus_sg_buffer_list; 82250199Sgrehan 83250199Sgrehantypedef struct { 84250199Sgrehan uint32_t current_interrupt_mask; 85250199Sgrehan uint32_t current_read_index; 86250199Sgrehan uint32_t current_write_index; 87250199Sgrehan uint32_t bytes_avail_to_read; 88250199Sgrehan uint32_t bytes_avail_to_write; 89250199Sgrehan} hv_vmbus_ring_buffer_debug_info; 90250199Sgrehan 91250199Sgrehantypedef struct { 92250199Sgrehan uint32_t rel_id; 93250199Sgrehan hv_vmbus_channel_state state; 94250199Sgrehan hv_guid interface_type; 95250199Sgrehan hv_guid interface_instance; 96250199Sgrehan uint32_t monitor_id; 97250199Sgrehan uint32_t server_monitor_pending; 98250199Sgrehan uint32_t server_monitor_latency; 99250199Sgrehan uint32_t server_monitor_connection_id; 100250199Sgrehan uint32_t client_monitor_pending; 101250199Sgrehan uint32_t client_monitor_latency; 102250199Sgrehan uint32_t client_monitor_connection_id; 103250199Sgrehan hv_vmbus_ring_buffer_debug_info inbound; 104250199Sgrehan hv_vmbus_ring_buffer_debug_info outbound; 105250199Sgrehan} hv_vmbus_channel_debug_info; 106250199Sgrehan 107250199Sgrehantypedef union { 108250199Sgrehan hv_vmbus_channel_version_supported version_supported; 109250199Sgrehan hv_vmbus_channel_open_result open_result; 110250199Sgrehan hv_vmbus_channel_gpadl_torndown gpadl_torndown; 111250199Sgrehan hv_vmbus_channel_gpadl_created gpadl_created; 112250199Sgrehan hv_vmbus_channel_version_response version_response; 113250199Sgrehan} hv_vmbus_channel_msg_response; 114250199Sgrehan 115250199Sgrehan/* 116250199Sgrehan * Represents each channel msg on the vmbus connection 117250199Sgrehan * This is a variable-size data structure depending on 118250199Sgrehan * the msg type itself 119250199Sgrehan */ 120250199Sgrehantypedef struct hv_vmbus_channel_msg_info { 121250199Sgrehan /* 122250199Sgrehan * Bookkeeping stuff 123250199Sgrehan */ 124250199Sgrehan TAILQ_ENTRY(hv_vmbus_channel_msg_info) msg_list_entry; 125250199Sgrehan /* 126250199Sgrehan * So far, this is only used to handle 127250199Sgrehan * gpadl body message 128250199Sgrehan */ 129250199Sgrehan TAILQ_HEAD(, hv_vmbus_channel_msg_info) sub_msg_list_anchor; 130250199Sgrehan /* 131250199Sgrehan * Synchronize the request/response if 132250199Sgrehan * needed. 133250199Sgrehan * KYS: Use a semaphore for now. 134250199Sgrehan * Not perf critical. 135250199Sgrehan */ 136250199Sgrehan struct sema wait_sema; 137250199Sgrehan hv_vmbus_channel_msg_response response; 138250199Sgrehan uint32_t message_size; 139250199Sgrehan /** 140250199Sgrehan * The channel message that goes out on 141250199Sgrehan * the "wire". It will contain at 142250199Sgrehan * minimum the 143250199Sgrehan * hv_vmbus_channel_msg_header 144250199Sgrehan * header. 145250199Sgrehan */ 146250199Sgrehan unsigned char msg[0]; 147250199Sgrehan} hv_vmbus_channel_msg_info; 148250199Sgrehan 149250199Sgrehan/* 150250199Sgrehan * The format must be the same as hv_vm_data_gpa_direct 151250199Sgrehan */ 152250199Sgrehantypedef struct hv_vmbus_channel_packet_page_buffer { 153250199Sgrehan uint16_t type; 154250199Sgrehan uint16_t data_offset8; 155250199Sgrehan uint16_t length8; 156250199Sgrehan uint16_t flags; 157250199Sgrehan uint64_t transaction_id; 158250199Sgrehan uint32_t reserved; 159250199Sgrehan uint32_t range_count; 160250199Sgrehan hv_vmbus_page_buffer range[HV_MAX_PAGE_BUFFER_COUNT]; 161250199Sgrehan} __packed hv_vmbus_channel_packet_page_buffer; 162250199Sgrehan 163250199Sgrehan/* 164250199Sgrehan * The format must be the same as hv_vm_data_gpa_direct 165250199Sgrehan */ 166250199Sgrehantypedef struct hv_vmbus_channel_packet_multipage_buffer { 167250199Sgrehan uint16_t type; 168250199Sgrehan uint16_t data_offset8; 169250199Sgrehan uint16_t length8; 170250199Sgrehan uint16_t flags; 171250199Sgrehan uint64_t transaction_id; 172250199Sgrehan uint32_t reserved; 173250199Sgrehan uint32_t range_count; /* Always 1 in this case */ 174250199Sgrehan hv_vmbus_multipage_buffer range; 175250199Sgrehan} __packed hv_vmbus_channel_packet_multipage_buffer; 176250199Sgrehan 177250199Sgrehanenum { 178250199Sgrehan HV_VMBUS_MESSAGE_CONNECTION_ID = 1, 179250199Sgrehan HV_VMBUS_MESSAGE_PORT_ID = 1, 180250199Sgrehan HV_VMBUS_EVENT_CONNECTION_ID = 2, 181250199Sgrehan HV_VMBUS_EVENT_PORT_ID = 2, 182250199Sgrehan HV_VMBUS_MONITOR_CONNECTION_ID = 3, 183250199Sgrehan HV_VMBUS_MONITOR_PORT_ID = 3, 184250199Sgrehan HV_VMBUS_MESSAGE_SINT = 2 185250199Sgrehan}; 186250199Sgrehan 187250199Sgrehan#define HV_PRESENT_BIT 0x80000000 188250199Sgrehan 189250199Sgrehan#define HV_HYPERCALL_PARAM_ALIGN sizeof(uint64_t) 190250199Sgrehan 191250199Sgrehantypedef struct { 192250199Sgrehan uint64_t guest_id; 193250199Sgrehan void* hypercall_page; 194250199Sgrehan hv_bool_uint8_t syn_ic_initialized; 195283280Swhu 196283280Swhu hv_vmbus_handle syn_ic_msg_page[MAXCPU]; 197283280Swhu hv_vmbus_handle syn_ic_event_page[MAXCPU]; 198250199Sgrehan /* 199283280Swhu * For FreeBSD cpuid to Hyper-V vcpuid mapping. 200250199Sgrehan */ 201283280Swhu uint32_t hv_vcpu_index[MAXCPU]; 202250199Sgrehan /* 203283280Swhu * Each cpu has its own software interrupt handler for channel 204283280Swhu * event and msg handling. 205250199Sgrehan */ 206283280Swhu struct intr_event *hv_event_intr_event[MAXCPU]; 207283280Swhu struct intr_event *hv_msg_intr_event[MAXCPU]; 208283280Swhu void *event_swintr[MAXCPU]; 209283280Swhu void *msg_swintr[MAXCPU]; 210283280Swhu /* 211283280Swhu * Host use this vector to intrrupt guest for vmbus channel 212283280Swhu * event and msg. 213283280Swhu */ 214283280Swhu unsigned int hv_cb_vector; 215250199Sgrehan} hv_vmbus_context; 216250199Sgrehan 217250199Sgrehan/* 218250199Sgrehan * Define hypervisor message types 219250199Sgrehan */ 220250199Sgrehantypedef enum { 221250199Sgrehan 222250199Sgrehan HV_MESSAGE_TYPE_NONE = 0x00000000, 223250199Sgrehan 224250199Sgrehan /* 225250199Sgrehan * Memory access messages 226250199Sgrehan */ 227250199Sgrehan HV_MESSAGE_TYPE_UNMAPPED_GPA = 0x80000000, 228250199Sgrehan HV_MESSAGE_TYPE_GPA_INTERCEPT = 0x80000001, 229250199Sgrehan 230250199Sgrehan /* 231250199Sgrehan * Timer notification messages 232250199Sgrehan */ 233250199Sgrehan HV_MESSAGE_TIMER_EXPIRED = 0x80000010, 234250199Sgrehan 235250199Sgrehan /* 236250199Sgrehan * Error messages 237250199Sgrehan */ 238250199Sgrehan HV_MESSAGE_TYPE_INVALID_VP_REGISTER_VALUE = 0x80000020, 239250199Sgrehan HV_MESSAGE_TYPE_UNRECOVERABLE_EXCEPTION = 0x80000021, 240250199Sgrehan HV_MESSAGE_TYPE_UNSUPPORTED_FEATURE = 0x80000022, 241250199Sgrehan 242250199Sgrehan /* 243250199Sgrehan * Trace buffer complete messages 244250199Sgrehan */ 245250199Sgrehan HV_MESSAGE_TYPE_EVENT_LOG_BUFFER_COMPLETE = 0x80000040, 246250199Sgrehan 247250199Sgrehan /* 248250199Sgrehan * Platform-specific processor intercept messages 249250199Sgrehan */ 250250199Sgrehan HV_MESSAGE_TYPE_X64_IO_PORT_INTERCEPT = 0x80010000, 251250199Sgrehan HV_MESSAGE_TYPE_X64_MSR_INTERCEPT = 0x80010001, 252250199Sgrehan HV_MESSAGE_TYPE_X64_CPU_INTERCEPT = 0x80010002, 253250199Sgrehan HV_MESSAGE_TYPE_X64_EXCEPTION_INTERCEPT = 0x80010003, 254250199Sgrehan HV_MESSAGE_TYPE_X64_APIC_EOI = 0x80010004, 255250199Sgrehan HV_MESSAGE_TYPE_X64_LEGACY_FP_ERROR = 0x80010005 256250199Sgrehan 257250199Sgrehan} hv_vmbus_msg_type; 258250199Sgrehan 259250199Sgrehan/* 260250199Sgrehan * Define port identifier type 261250199Sgrehan */ 262250199Sgrehantypedef union _hv_vmbus_port_id { 263250199Sgrehan uint32_t as_uint32_t; 264250199Sgrehan struct { 265250199Sgrehan uint32_t id:24; 266250199Sgrehan uint32_t reserved:8; 267250199Sgrehan } u ; 268250199Sgrehan} hv_vmbus_port_id; 269250199Sgrehan 270250199Sgrehan/* 271250199Sgrehan * Define synthetic interrupt controller message flag 272250199Sgrehan */ 273250199Sgrehantypedef union { 274250199Sgrehan uint8_t as_uint8_t; 275250199Sgrehan struct { 276250199Sgrehan uint8_t message_pending:1; 277250199Sgrehan uint8_t reserved:7; 278256276Sdim } u; 279250199Sgrehan} hv_vmbus_msg_flags; 280250199Sgrehan 281250199Sgrehantypedef uint64_t hv_vmbus_partition_id; 282250199Sgrehan 283250199Sgrehan/* 284250199Sgrehan * Define synthetic interrupt controller message header 285250199Sgrehan */ 286250199Sgrehantypedef struct { 287250199Sgrehan hv_vmbus_msg_type message_type; 288250199Sgrehan uint8_t payload_size; 289250199Sgrehan hv_vmbus_msg_flags message_flags; 290250199Sgrehan uint8_t reserved[2]; 291250199Sgrehan union { 292250199Sgrehan hv_vmbus_partition_id sender; 293250199Sgrehan hv_vmbus_port_id port; 294250199Sgrehan } u; 295250199Sgrehan} hv_vmbus_msg_header; 296250199Sgrehan 297250199Sgrehan/* 298250199Sgrehan * Define synthetic interrupt controller message format 299250199Sgrehan */ 300250199Sgrehantypedef struct { 301250199Sgrehan hv_vmbus_msg_header header; 302250199Sgrehan union { 303250199Sgrehan uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; 304250199Sgrehan } u ; 305250199Sgrehan} hv_vmbus_message; 306250199Sgrehan 307250199Sgrehan/* 308250199Sgrehan * Maximum channels is determined by the size of the interrupt 309250199Sgrehan * page which is PAGE_SIZE. 1/2 of PAGE_SIZE is for 310250199Sgrehan * send endpoint interrupt and the other is receive 311250199Sgrehan * endpoint interrupt. 312250199Sgrehan * 313250199Sgrehan * Note: (PAGE_SIZE >> 1) << 3 allocates 16348 channels 314250199Sgrehan */ 315250199Sgrehan#define HV_MAX_NUM_CHANNELS (PAGE_SIZE >> 1) << 3 316250199Sgrehan 317250199Sgrehan/* 318250199Sgrehan * (The value here must be in multiple of 32) 319250199Sgrehan */ 320250199Sgrehan#define HV_MAX_NUM_CHANNELS_SUPPORTED 256 321250199Sgrehan 322250199Sgrehan/* 323250199Sgrehan * VM Bus connection states 324250199Sgrehan */ 325250199Sgrehantypedef enum { 326250199Sgrehan HV_DISCONNECTED, 327250199Sgrehan HV_CONNECTING, 328250199Sgrehan HV_CONNECTED, 329250199Sgrehan HV_DISCONNECTING 330250199Sgrehan} hv_vmbus_connect_state; 331250199Sgrehan 332250199Sgrehan#define HV_MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT 333250199Sgrehan 334250199Sgrehan 335250199Sgrehantypedef struct { 336250199Sgrehan hv_vmbus_connect_state connect_state; 337250199Sgrehan uint32_t next_gpadl_handle; 338250199Sgrehan /** 339250199Sgrehan * Represents channel interrupts. Each bit position 340250199Sgrehan * represents a channel. 341250199Sgrehan * When a channel sends an interrupt via VMBUS, it 342250199Sgrehan * finds its bit in the send_interrupt_page, set it and 343250199Sgrehan * calls Hv to generate a port event. The other end 344250199Sgrehan * receives the port event and parse the 345250199Sgrehan * recv_interrupt_page to see which bit is set 346250199Sgrehan */ 347250199Sgrehan void *interrupt_page; 348250199Sgrehan void *send_interrupt_page; 349250199Sgrehan void *recv_interrupt_page; 350250199Sgrehan /* 351250199Sgrehan * 2 pages - 1st page for parent->child 352250199Sgrehan * notification and 2nd is child->parent 353250199Sgrehan * notification 354250199Sgrehan */ 355250199Sgrehan void *monitor_pages; 356250199Sgrehan TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor; 357250199Sgrehan struct mtx channel_msg_lock; 358250199Sgrehan /** 359283280Swhu * List of primary channels. Sub channels will be linked 360283280Swhu * under their primary channel. 361250199Sgrehan */ 362250199Sgrehan TAILQ_HEAD(, hv_vmbus_channel) channel_anchor; 363250199Sgrehan struct mtx channel_lock; 364250199Sgrehan 365295948Ssephe /** 366295948Ssephe * channel table for fast lookup through id. 367295948Ssephe */ 368295948Ssephe hv_vmbus_channel **channels; 369250199Sgrehan hv_vmbus_handle work_queue; 370250199Sgrehan struct sema control_sema; 371250199Sgrehan} hv_vmbus_connection; 372250199Sgrehan 373250199Sgrehantypedef union { 374250199Sgrehan uint64_t as_uint64_t; 375250199Sgrehan struct { 376250199Sgrehan uint64_t build_number : 16; 377250199Sgrehan uint64_t service_version : 8; /* Service Pack, etc. */ 378250199Sgrehan uint64_t minor_version : 8; 379250199Sgrehan uint64_t major_version : 8; 380250199Sgrehan /* 381250199Sgrehan * HV_GUEST_OS_MICROSOFT_IDS (If Vendor=MS) 382250199Sgrehan * HV_GUEST_OS_VENDOR 383250199Sgrehan */ 384250199Sgrehan uint64_t os_id : 8; 385250199Sgrehan uint64_t vendor_id : 16; 386256276Sdim } u; 387250199Sgrehan} hv_vmbus_x64_msr_guest_os_id_contents; 388250199Sgrehan 389250199Sgrehan 390250199Sgrehantypedef union { 391250199Sgrehan uint64_t as_uint64_t; 392250199Sgrehan struct { 393250199Sgrehan uint64_t enable :1; 394250199Sgrehan uint64_t reserved :11; 395250199Sgrehan uint64_t guest_physical_address :52; 396256276Sdim } u; 397250199Sgrehan} hv_vmbus_x64_msr_hypercall_contents; 398250199Sgrehan 399250199Sgrehantypedef union { 400250199Sgrehan uint32_t as_uint32_t; 401250199Sgrehan struct { 402250199Sgrehan uint32_t group_enable :4; 403250199Sgrehan uint32_t rsvd_z :28; 404256276Sdim } u; 405250199Sgrehan} hv_vmbus_monitor_trigger_state; 406250199Sgrehan 407250199Sgrehantypedef union { 408250199Sgrehan uint64_t as_uint64_t; 409250199Sgrehan struct { 410250199Sgrehan uint32_t pending; 411250199Sgrehan uint32_t armed; 412256276Sdim } u; 413250199Sgrehan} hv_vmbus_monitor_trigger_group; 414250199Sgrehan 415250199Sgrehantypedef struct { 416250199Sgrehan hv_vmbus_connection_id connection_id; 417250199Sgrehan uint16_t flag_number; 418250199Sgrehan uint16_t rsvd_z; 419250199Sgrehan} hv_vmbus_monitor_parameter; 420250199Sgrehan 421250199Sgrehan/* 422250199Sgrehan * hv_vmbus_monitor_page Layout 423250199Sgrehan * ------------------------------------------------------ 424250199Sgrehan * | 0 | trigger_state (4 bytes) | Rsvd1 (4 bytes) | 425250199Sgrehan * | 8 | trigger_group[0] | 426250199Sgrehan * | 10 | trigger_group[1] | 427250199Sgrehan * | 18 | trigger_group[2] | 428250199Sgrehan * | 20 | trigger_group[3] | 429250199Sgrehan * | 28 | Rsvd2[0] | 430250199Sgrehan * | 30 | Rsvd2[1] | 431250199Sgrehan * | 38 | Rsvd2[2] | 432250199Sgrehan * | 40 | next_check_time[0][0] | next_check_time[0][1] | 433250199Sgrehan * | ... | 434250199Sgrehan * | 240 | latency[0][0..3] | 435250199Sgrehan * | 340 | Rsvz3[0] | 436250199Sgrehan * | 440 | parameter[0][0] | 437250199Sgrehan * | 448 | parameter[0][1] | 438250199Sgrehan * | ... | 439250199Sgrehan * | 840 | Rsvd4[0] | 440250199Sgrehan * ------------------------------------------------------ 441250199Sgrehan */ 442250199Sgrehan 443250199Sgrehantypedef struct { 444250199Sgrehan hv_vmbus_monitor_trigger_state trigger_state; 445250199Sgrehan uint32_t rsvd_z1; 446250199Sgrehan 447250199Sgrehan hv_vmbus_monitor_trigger_group trigger_group[4]; 448250199Sgrehan uint64_t rsvd_z2[3]; 449250199Sgrehan 450250199Sgrehan int32_t next_check_time[4][32]; 451250199Sgrehan 452250199Sgrehan uint16_t latency[4][32]; 453250199Sgrehan uint64_t rsvd_z3[32]; 454250199Sgrehan 455250199Sgrehan hv_vmbus_monitor_parameter parameter[4][32]; 456250199Sgrehan 457250199Sgrehan uint8_t rsvd_z4[1984]; 458250199Sgrehan} hv_vmbus_monitor_page; 459250199Sgrehan 460250199Sgrehan/* 461250199Sgrehan * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent 462250199Sgrehan * is set by CPUID(HV_CPU_ID_FUNCTION_VERSION_AND_FEATURES). 463250199Sgrehan */ 464250199Sgrehantypedef enum { 465250199Sgrehan HV_CPU_ID_FUNCTION_VERSION_AND_FEATURES = 0x00000001, 466250199Sgrehan HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION = 0x40000000, 467250199Sgrehan HV_CPU_ID_FUNCTION_HV_INTERFACE = 0x40000001, 468250199Sgrehan /* 469250199Sgrehan * The remaining functions depend on the value 470250199Sgrehan * of hv_cpu_id_function_interface 471250199Sgrehan */ 472250199Sgrehan HV_CPU_ID_FUNCTION_MS_HV_VERSION = 0x40000002, 473250199Sgrehan HV_CPU_ID_FUNCTION_MS_HV_FEATURES = 0x40000003, 474250199Sgrehan HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION = 0x40000004, 475303984Sglebius HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005, 476303984Sglebius HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE = 0x40000006 477250199Sgrehan} hv_vmbus_cpuid_function; 478250199Sgrehan 479303984Sglebius#define HV_FEATURE_MSR_TIME_REFCNT (1 << 1) 480303984Sglebius#define HV_FEATURE_MSR_SYNCIC (1 << 2) 481303984Sglebius#define HV_FEATURE_MSR_STIMER (1 << 3) 482303984Sglebius#define HV_FEATURE_MSR_APIC (1 << 4) 483303984Sglebius#define HV_FEATURE_MSR_HYPERCALL (1 << 5) 484303984Sglebius#define HV_FEATURE_MSR_GUEST_IDLE (1 << 10) 485303984Sglebius 486250199Sgrehan/* 487250199Sgrehan * Define the format of the SIMP register 488250199Sgrehan */ 489250199Sgrehantypedef union { 490250199Sgrehan uint64_t as_uint64_t; 491250199Sgrehan struct { 492250199Sgrehan uint64_t simp_enabled : 1; 493250199Sgrehan uint64_t preserved : 11; 494250199Sgrehan uint64_t base_simp_gpa : 52; 495256276Sdim } u; 496250199Sgrehan} hv_vmbus_synic_simp; 497250199Sgrehan 498250199Sgrehan/* 499250199Sgrehan * Define the format of the SIEFP register 500250199Sgrehan */ 501250199Sgrehantypedef union { 502250199Sgrehan uint64_t as_uint64_t; 503250199Sgrehan struct { 504250199Sgrehan uint64_t siefp_enabled : 1; 505250199Sgrehan uint64_t preserved : 11; 506250199Sgrehan uint64_t base_siefp_gpa : 52; 507256276Sdim } u; 508250199Sgrehan} hv_vmbus_synic_siefp; 509250199Sgrehan 510250199Sgrehan/* 511250199Sgrehan * Define synthetic interrupt source 512250199Sgrehan */ 513250199Sgrehantypedef union { 514250199Sgrehan uint64_t as_uint64_t; 515250199Sgrehan struct { 516250199Sgrehan uint64_t vector : 8; 517250199Sgrehan uint64_t reserved1 : 8; 518250199Sgrehan uint64_t masked : 1; 519250199Sgrehan uint64_t auto_eoi : 1; 520250199Sgrehan uint64_t reserved2 : 46; 521256276Sdim } u; 522250199Sgrehan} hv_vmbus_synic_sint; 523250199Sgrehan 524250199Sgrehan/* 525295789Ssephe * Timer configuration register. 526295789Ssephe */ 527295789Ssepheunion hv_timer_config { 528295789Ssephe uint64_t as_uint64; 529295789Ssephe struct { 530295789Ssephe uint64_t enable:1; 531295789Ssephe uint64_t periodic:1; 532295789Ssephe uint64_t lazy:1; 533295789Ssephe uint64_t auto_enable:1; 534295789Ssephe uint64_t reserved_z0:12; 535295789Ssephe uint64_t sintx:4; 536295789Ssephe uint64_t reserved_z1:44; 537295789Ssephe }; 538295789Ssephe}; 539295789Ssephe 540295789Ssephe/* 541250199Sgrehan * Define syn_ic control register 542250199Sgrehan */ 543250199Sgrehantypedef union _hv_vmbus_synic_scontrol { 544250199Sgrehan uint64_t as_uint64_t; 545250199Sgrehan struct { 546250199Sgrehan uint64_t enable : 1; 547250199Sgrehan uint64_t reserved : 63; 548256276Sdim } u; 549250199Sgrehan} hv_vmbus_synic_scontrol; 550250199Sgrehan 551250199Sgrehan/* 552250199Sgrehan * Define the hv_vmbus_post_message hypercall input structure 553250199Sgrehan */ 554250199Sgrehantypedef struct { 555250199Sgrehan hv_vmbus_connection_id connection_id; 556250199Sgrehan uint32_t reserved; 557250199Sgrehan hv_vmbus_msg_type message_type; 558250199Sgrehan uint32_t payload_size; 559250199Sgrehan uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; 560250199Sgrehan} hv_vmbus_input_post_message; 561250199Sgrehan 562250199Sgrehan/* 563250199Sgrehan * Define the synthetic interrupt controller event flags format 564250199Sgrehan */ 565250199Sgrehantypedef union { 566250199Sgrehan uint8_t flags8[HV_EVENT_FLAGS_BYTE_COUNT]; 567250199Sgrehan uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT]; 568250199Sgrehan} hv_vmbus_synic_event_flags; 569250199Sgrehan 570295789Ssephe#define HV_X64_CPUID_MIN (0x40000005) 571295789Ssephe#define HV_X64_CPUID_MAX (0x4000ffff) 572295789Ssephe 573295789Ssephe/* 574295789Ssephe * Declare the MSR used to identify the guest OS 575295789Ssephe */ 576295789Ssephe#define HV_X64_MSR_GUEST_OS_ID (0x40000000) 577295789Ssephe/* 578295789Ssephe * Declare the MSR used to setup pages used to communicate with the hypervisor 579295789Ssephe */ 580295789Ssephe#define HV_X64_MSR_HYPERCALL (0x40000001) 581283280Swhu/* MSR used to provide vcpu index */ 582295789Ssephe#define HV_X64_MSR_VP_INDEX (0x40000002) 583250199Sgrehan 584295789Ssephe#define HV_X64_MSR_TIME_REF_COUNT (0x40000020) 585295789Ssephe 586250199Sgrehan/* 587250199Sgrehan * Define synthetic interrupt controller model specific registers 588250199Sgrehan */ 589250199Sgrehan#define HV_X64_MSR_SCONTROL (0x40000080) 590250199Sgrehan#define HV_X64_MSR_SVERSION (0x40000081) 591250199Sgrehan#define HV_X64_MSR_SIEFP (0x40000082) 592250199Sgrehan#define HV_X64_MSR_SIMP (0x40000083) 593250199Sgrehan#define HV_X64_MSR_EOM (0x40000084) 594250199Sgrehan 595250199Sgrehan#define HV_X64_MSR_SINT0 (0x40000090) 596250199Sgrehan#define HV_X64_MSR_SINT1 (0x40000091) 597250199Sgrehan#define HV_X64_MSR_SINT2 (0x40000092) 598250199Sgrehan#define HV_X64_MSR_SINT3 (0x40000093) 599250199Sgrehan#define HV_X64_MSR_SINT4 (0x40000094) 600250199Sgrehan#define HV_X64_MSR_SINT5 (0x40000095) 601250199Sgrehan#define HV_X64_MSR_SINT6 (0x40000096) 602250199Sgrehan#define HV_X64_MSR_SINT7 (0x40000097) 603250199Sgrehan#define HV_X64_MSR_SINT8 (0x40000098) 604250199Sgrehan#define HV_X64_MSR_SINT9 (0x40000099) 605250199Sgrehan#define HV_X64_MSR_SINT10 (0x4000009A) 606250199Sgrehan#define HV_X64_MSR_SINT11 (0x4000009B) 607250199Sgrehan#define HV_X64_MSR_SINT12 (0x4000009C) 608250199Sgrehan#define HV_X64_MSR_SINT13 (0x4000009D) 609250199Sgrehan#define HV_X64_MSR_SINT14 (0x4000009E) 610250199Sgrehan#define HV_X64_MSR_SINT15 (0x4000009F) 611250199Sgrehan 612250199Sgrehan/* 613295789Ssephe * Synthetic Timer MSRs. Four timers per vcpu. 614295789Ssephe */ 615295789Ssephe#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0 616295789Ssephe#define HV_X64_MSR_STIMER0_COUNT 0x400000B1 617295789Ssephe#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2 618295789Ssephe#define HV_X64_MSR_STIMER1_COUNT 0x400000B3 619295789Ssephe#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4 620295789Ssephe#define HV_X64_MSR_STIMER2_COUNT 0x400000B5 621295789Ssephe#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6 622295789Ssephe#define HV_X64_MSR_STIMER3_COUNT 0x400000B7 623295789Ssephe 624295789Ssephe/* 625250199Sgrehan * Declare the various hypercall operations 626250199Sgrehan */ 627250199Sgrehantypedef enum { 628250199Sgrehan HV_CALL_POST_MESSAGE = 0x005c, 629250199Sgrehan HV_CALL_SIGNAL_EVENT = 0x005d, 630250199Sgrehan} hv_vmbus_call_code; 631250199Sgrehan 632250199Sgrehan/** 633250199Sgrehan * Global variables 634250199Sgrehan */ 635250199Sgrehan 636250199Sgrehanextern hv_vmbus_context hv_vmbus_g_context; 637250199Sgrehanextern hv_vmbus_connection hv_vmbus_g_connection; 638250199Sgrehan 639303984Sglebiusextern u_int hyperv_features; 640303984Sglebiusextern u_int hyperv_recommends; 641303984Sglebius 642293820Sdelphijtypedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg); 643250199Sgrehan 644293820Sdelphijtypedef struct hv_vmbus_channel_msg_table_entry { 645293820Sdelphij hv_vmbus_channel_msg_type messageType; 646293820Sdelphij 647293820Sdelphij bool handler_no_sleep; /* true: the handler doesn't sleep */ 648293820Sdelphij vmbus_msg_handler messageHandler; 649293820Sdelphij} hv_vmbus_channel_msg_table_entry; 650293820Sdelphij 651293820Sdelphijextern hv_vmbus_channel_msg_table_entry g_channel_message_table[]; 652293820Sdelphij 653250199Sgrehan/* 654250199Sgrehan * Private, VM Bus functions 655250199Sgrehan */ 656250199Sgrehan 657250199Sgrehanint hv_vmbus_ring_buffer_init( 658250199Sgrehan hv_vmbus_ring_buffer_info *ring_info, 659250199Sgrehan void *buffer, 660250199Sgrehan uint32_t buffer_len); 661250199Sgrehan 662250199Sgrehanvoid hv_ring_buffer_cleanup( 663250199Sgrehan hv_vmbus_ring_buffer_info *ring_info); 664250199Sgrehan 665250199Sgrehanint hv_ring_buffer_write( 666250199Sgrehan hv_vmbus_ring_buffer_info *ring_info, 667250199Sgrehan hv_vmbus_sg_buffer_list sg_buffers[], 668283280Swhu uint32_t sg_buff_count, 669283280Swhu boolean_t *need_sig); 670250199Sgrehan 671250199Sgrehanint hv_ring_buffer_peek( 672250199Sgrehan hv_vmbus_ring_buffer_info *ring_info, 673250199Sgrehan void *buffer, 674250199Sgrehan uint32_t buffer_len); 675250199Sgrehan 676250199Sgrehanint hv_ring_buffer_read( 677250199Sgrehan hv_vmbus_ring_buffer_info *ring_info, 678250199Sgrehan void *buffer, 679250199Sgrehan uint32_t buffer_len, 680250199Sgrehan uint32_t offset); 681250199Sgrehan 682250199Sgrehanuint32_t hv_vmbus_get_ring_buffer_interrupt_mask( 683250199Sgrehan hv_vmbus_ring_buffer_info *ring_info); 684250199Sgrehan 685250199Sgrehanvoid hv_vmbus_dump_ring_info( 686250199Sgrehan hv_vmbus_ring_buffer_info *ring_info, 687250199Sgrehan char *prefix); 688250199Sgrehan 689283280Swhuvoid hv_ring_buffer_read_begin( 690283280Swhu hv_vmbus_ring_buffer_info *ring_info); 691283280Swhu 692283280Swhuuint32_t hv_ring_buffer_read_end( 693283280Swhu hv_vmbus_ring_buffer_info *ring_info); 694283280Swhu 695250199Sgrehanhv_vmbus_channel* hv_vmbus_allocate_channel(void); 696250199Sgrehanvoid hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel); 697250199Sgrehanvoid hv_vmbus_on_channel_message(void *context); 698250199Sgrehanint hv_vmbus_request_channel_offers(void); 699250199Sgrehanvoid hv_vmbus_release_unattached_channels(void); 700250199Sgrehanint hv_vmbus_init(void); 701250199Sgrehanvoid hv_vmbus_cleanup(void); 702250199Sgrehan 703250199Sgrehanuint16_t hv_vmbus_post_msg_via_msg_ipc( 704250199Sgrehan hv_vmbus_connection_id connection_id, 705250199Sgrehan hv_vmbus_msg_type message_type, 706250199Sgrehan void *payload, 707250199Sgrehan size_t payload_size); 708250199Sgrehan 709283280Swhuuint16_t hv_vmbus_signal_event(void *con_id); 710250199Sgrehanvoid hv_vmbus_synic_init(void *irq_arg); 711250199Sgrehanvoid hv_vmbus_synic_cleanup(void *arg); 712250199Sgrehanint hv_vmbus_query_hypervisor_presence(void); 713250199Sgrehan 714250199Sgrehanstruct hv_device* hv_vmbus_child_device_create( 715250199Sgrehan hv_guid device_type, 716250199Sgrehan hv_guid device_instance, 717250199Sgrehan hv_vmbus_channel *channel); 718250199Sgrehan 719250199Sgrehanint hv_vmbus_child_device_register( 720250199Sgrehan struct hv_device *child_dev); 721250199Sgrehanint hv_vmbus_child_device_unregister( 722250199Sgrehan struct hv_device *child_dev); 723250199Sgrehan 724250199Sgrehan/** 725250199Sgrehan * Connection interfaces 726250199Sgrehan */ 727250199Sgrehanint hv_vmbus_connect(void); 728250199Sgrehanint hv_vmbus_disconnect(void); 729250199Sgrehanint hv_vmbus_post_message(void *buffer, size_t buf_size); 730283280Swhuint hv_vmbus_set_event(hv_vmbus_channel *channel); 731250199Sgrehanvoid hv_vmbus_on_events(void *); 732250199Sgrehan 733295789Ssephe/** 734295789Ssephe * Event Timer interfaces 735295789Ssephe */ 736295789Ssephevoid hv_et_init(void); 737295789Ssephevoid hv_et_intr(struct trapframe*); 738250199Sgrehan 739250199Sgrehan/* 740250199Sgrehan * The guest OS needs to register the guest ID with the hypervisor. 741250199Sgrehan * The guest ID is a 64 bit entity and the structure of this ID is 742250199Sgrehan * specified in the Hyper-V specification: 743250199Sgrehan * 744250199Sgrehan * http://msdn.microsoft.com/en-us/library/windows/ 745250199Sgrehan * hardware/ff542653%28v=vs.85%29.aspx 746250199Sgrehan * 747250199Sgrehan * While the current guideline does not specify how FreeBSD guest ID(s) 748250199Sgrehan * need to be generated, our plan is to publish the guidelines for 749250199Sgrehan * FreeBSD and other guest operating systems that currently are hosted 750250199Sgrehan * on Hyper-V. The implementation here conforms to this yet 751250199Sgrehan * unpublished guidelines. 752250199Sgrehan * 753250199Sgrehan * Bit(s) 754250199Sgrehan * 63 - Indicates if the OS is Open Source or not; 1 is Open Source 755250199Sgrehan * 62:56 - Os Type; Linux is 0x100, FreeBSD is 0x200 756250199Sgrehan * 55:48 - Distro specific identification 757250199Sgrehan * 47:16 - FreeBSD kernel version number 758250199Sgrehan * 15:0 - Distro specific identification 759250199Sgrehan * 760250199Sgrehan */ 761250199Sgrehan 762250199Sgrehan#define HV_FREEBSD_VENDOR_ID 0x8200 763250199Sgrehan#define HV_FREEBSD_GUEST_ID hv_generate_guest_id(0,0) 764250199Sgrehan 765250199Sgrehanstatic inline uint64_t hv_generate_guest_id( 766250199Sgrehan uint8_t distro_id_part1, 767250199Sgrehan uint16_t distro_id_part2) 768250199Sgrehan{ 769250199Sgrehan uint64_t guest_id; 770250199Sgrehan guest_id = (((uint64_t)HV_FREEBSD_VENDOR_ID) << 48); 771250199Sgrehan guest_id |= (((uint64_t)(distro_id_part1)) << 48); 772250199Sgrehan guest_id |= (((uint64_t)(__FreeBSD_version)) << 16); /* in param.h */ 773250199Sgrehan guest_id |= ((uint64_t)(distro_id_part2)); 774250199Sgrehan return guest_id; 775250199Sgrehan} 776250199Sgrehan 777255414Sgrehantypedef struct { 778255414Sgrehan unsigned int vector; 779283280Swhu void *page_buffers[2 * MAXCPU]; 780255414Sgrehan} hv_setup_args; 781250199Sgrehan 782250199Sgrehan#endif /* __HYPERV_PRIV_H__ */ 783