1/*- 2 * Copyright (c) 2009-2012 Microsoft Corp. 3 * Copyright (c) 2012 NetApp Inc. 4 * Copyright (c) 2012 Citrix Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: releng/10.3/sys/dev/hyperv/vmbus/hv_vmbus_priv.h 303984 2016-08-12 04:01:16Z glebius $ 29 */ 30 31#ifndef __HYPERV_PRIV_H__ 32#define __HYPERV_PRIV_H__ 33 34#include <sys/param.h> 35#include <sys/lock.h> 36#include <sys/mutex.h> 37#include <sys/sema.h> 38 39#include <dev/hyperv/include/hyperv.h> 40 41 42/* 43 * Status codes for hypervisor operations. 44 */ 45 46typedef uint16_t hv_vmbus_status; 47 48#define HV_MESSAGE_SIZE (256) 49#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) 50#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) 51#define HV_ANY_VP (0xFFFFFFFF) 52 53/* 54 * Synthetic interrupt controller flag constants. 55 */ 56 57#define HV_EVENT_FLAGS_COUNT (256 * 8) 58#define HV_EVENT_FLAGS_BYTE_COUNT (256) 59#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(uint32_t)) 60 61/** 62 * max channel count <== event_flags_dword_count * bit_of_dword 63 */ 64#define HV_CHANNEL_DWORD_LEN (32) 65#define HV_CHANNEL_MAX_COUNT \ 66 ((HV_EVENT_FLAGS_DWORD_COUNT) * HV_CHANNEL_DWORD_LEN) 67/* 68 * MessageId: HV_STATUS_INSUFFICIENT_BUFFERS 69 * MessageText: 70 * You did not supply enough message buffers to send a message. 71 */ 72 73#define HV_STATUS_SUCCESS ((uint16_t)0) 74#define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013) 75 76typedef void (*hv_vmbus_channel_callback)(void *context); 77 78typedef struct { 79 void* data; 80 uint32_t length; 81} hv_vmbus_sg_buffer_list; 82 83typedef struct { 84 uint32_t current_interrupt_mask; 85 uint32_t current_read_index; 86 uint32_t current_write_index; 87 uint32_t bytes_avail_to_read; 88 uint32_t bytes_avail_to_write; 89} hv_vmbus_ring_buffer_debug_info; 90 91typedef struct { 92 uint32_t rel_id; 93 hv_vmbus_channel_state state; 94 hv_guid interface_type; 95 hv_guid interface_instance; 96 uint32_t monitor_id; 97 uint32_t server_monitor_pending; 98 uint32_t server_monitor_latency; 99 uint32_t server_monitor_connection_id; 100 uint32_t client_monitor_pending; 101 uint32_t client_monitor_latency; 102 uint32_t client_monitor_connection_id; 103 hv_vmbus_ring_buffer_debug_info inbound; 104 hv_vmbus_ring_buffer_debug_info outbound; 105} hv_vmbus_channel_debug_info; 106 107typedef union { 108 hv_vmbus_channel_version_supported version_supported; 109 hv_vmbus_channel_open_result open_result; 110 hv_vmbus_channel_gpadl_torndown gpadl_torndown; 111 hv_vmbus_channel_gpadl_created gpadl_created; 112 hv_vmbus_channel_version_response version_response; 113} hv_vmbus_channel_msg_response; 114 115/* 116 * Represents each channel msg on the vmbus connection 117 * This is a variable-size data structure depending on 118 * the msg type itself 119 */ 120typedef struct hv_vmbus_channel_msg_info { 121 /* 122 * Bookkeeping stuff 123 */ 124 TAILQ_ENTRY(hv_vmbus_channel_msg_info) msg_list_entry; 125 /* 126 * So far, this is only used to handle 127 * gpadl body message 128 */ 129 TAILQ_HEAD(, hv_vmbus_channel_msg_info) sub_msg_list_anchor; 130 /* 131 * Synchronize the request/response if 132 * needed. 133 * KYS: Use a semaphore for now. 134 * Not perf critical. 135 */ 136 struct sema wait_sema; 137 hv_vmbus_channel_msg_response response; 138 uint32_t message_size; 139 /** 140 * The channel message that goes out on 141 * the "wire". It will contain at 142 * minimum the 143 * hv_vmbus_channel_msg_header 144 * header. 145 */ 146 unsigned char msg[0]; 147} hv_vmbus_channel_msg_info; 148 149/* 150 * The format must be the same as hv_vm_data_gpa_direct 151 */ 152typedef struct hv_vmbus_channel_packet_page_buffer { 153 uint16_t type; 154 uint16_t data_offset8; 155 uint16_t length8; 156 uint16_t flags; 157 uint64_t transaction_id; 158 uint32_t reserved; 159 uint32_t range_count; 160 hv_vmbus_page_buffer range[HV_MAX_PAGE_BUFFER_COUNT]; 161} __packed hv_vmbus_channel_packet_page_buffer; 162 163/* 164 * The format must be the same as hv_vm_data_gpa_direct 165 */ 166typedef struct hv_vmbus_channel_packet_multipage_buffer { 167 uint16_t type; 168 uint16_t data_offset8; 169 uint16_t length8; 170 uint16_t flags; 171 uint64_t transaction_id; 172 uint32_t reserved; 173 uint32_t range_count; /* Always 1 in this case */ 174 hv_vmbus_multipage_buffer range; 175} __packed hv_vmbus_channel_packet_multipage_buffer; 176 177enum { 178 HV_VMBUS_MESSAGE_CONNECTION_ID = 1, 179 HV_VMBUS_MESSAGE_PORT_ID = 1, 180 HV_VMBUS_EVENT_CONNECTION_ID = 2, 181 HV_VMBUS_EVENT_PORT_ID = 2, 182 HV_VMBUS_MONITOR_CONNECTION_ID = 3, 183 HV_VMBUS_MONITOR_PORT_ID = 3, 184 HV_VMBUS_MESSAGE_SINT = 2 185}; 186 187#define HV_PRESENT_BIT 0x80000000 188 189#define HV_HYPERCALL_PARAM_ALIGN sizeof(uint64_t) 190 191typedef struct { 192 uint64_t guest_id; 193 void* hypercall_page; 194 hv_bool_uint8_t syn_ic_initialized; 195 196 hv_vmbus_handle syn_ic_msg_page[MAXCPU]; 197 hv_vmbus_handle syn_ic_event_page[MAXCPU]; 198 /* 199 * For FreeBSD cpuid to Hyper-V vcpuid mapping. 200 */ 201 uint32_t hv_vcpu_index[MAXCPU]; 202 /* 203 * Each cpu has its own software interrupt handler for channel 204 * event and msg handling. 205 */ 206 struct intr_event *hv_event_intr_event[MAXCPU]; 207 struct intr_event *hv_msg_intr_event[MAXCPU]; 208 void *event_swintr[MAXCPU]; 209 void *msg_swintr[MAXCPU]; 210 /* 211 * Host use this vector to intrrupt guest for vmbus channel 212 * event and msg. 213 */ 214 unsigned int hv_cb_vector; 215} hv_vmbus_context; 216 217/* 218 * Define hypervisor message types 219 */ 220typedef enum { 221 222 HV_MESSAGE_TYPE_NONE = 0x00000000, 223 224 /* 225 * Memory access messages 226 */ 227 HV_MESSAGE_TYPE_UNMAPPED_GPA = 0x80000000, 228 HV_MESSAGE_TYPE_GPA_INTERCEPT = 0x80000001, 229 230 /* 231 * Timer notification messages 232 */ 233 HV_MESSAGE_TIMER_EXPIRED = 0x80000010, 234 235 /* 236 * Error messages 237 */ 238 HV_MESSAGE_TYPE_INVALID_VP_REGISTER_VALUE = 0x80000020, 239 HV_MESSAGE_TYPE_UNRECOVERABLE_EXCEPTION = 0x80000021, 240 HV_MESSAGE_TYPE_UNSUPPORTED_FEATURE = 0x80000022, 241 242 /* 243 * Trace buffer complete messages 244 */ 245 HV_MESSAGE_TYPE_EVENT_LOG_BUFFER_COMPLETE = 0x80000040, 246 247 /* 248 * Platform-specific processor intercept messages 249 */ 250 HV_MESSAGE_TYPE_X64_IO_PORT_INTERCEPT = 0x80010000, 251 HV_MESSAGE_TYPE_X64_MSR_INTERCEPT = 0x80010001, 252 HV_MESSAGE_TYPE_X64_CPU_INTERCEPT = 0x80010002, 253 HV_MESSAGE_TYPE_X64_EXCEPTION_INTERCEPT = 0x80010003, 254 HV_MESSAGE_TYPE_X64_APIC_EOI = 0x80010004, 255 HV_MESSAGE_TYPE_X64_LEGACY_FP_ERROR = 0x80010005 256 257} hv_vmbus_msg_type; 258 259/* 260 * Define port identifier type 261 */ 262typedef union _hv_vmbus_port_id { 263 uint32_t as_uint32_t; 264 struct { 265 uint32_t id:24; 266 uint32_t reserved:8; 267 } u ; 268} hv_vmbus_port_id; 269 270/* 271 * Define synthetic interrupt controller message flag 272 */ 273typedef union { 274 uint8_t as_uint8_t; 275 struct { 276 uint8_t message_pending:1; 277 uint8_t reserved:7; 278 } u; 279} hv_vmbus_msg_flags; 280 281typedef uint64_t hv_vmbus_partition_id; 282 283/* 284 * Define synthetic interrupt controller message header 285 */ 286typedef struct { 287 hv_vmbus_msg_type message_type; 288 uint8_t payload_size; 289 hv_vmbus_msg_flags message_flags; 290 uint8_t reserved[2]; 291 union { 292 hv_vmbus_partition_id sender; 293 hv_vmbus_port_id port; 294 } u; 295} hv_vmbus_msg_header; 296 297/* 298 * Define synthetic interrupt controller message format 299 */ 300typedef struct { 301 hv_vmbus_msg_header header; 302 union { 303 uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; 304 } u ; 305} hv_vmbus_message; 306 307/* 308 * Maximum channels is determined by the size of the interrupt 309 * page which is PAGE_SIZE. 1/2 of PAGE_SIZE is for 310 * send endpoint interrupt and the other is receive 311 * endpoint interrupt. 312 * 313 * Note: (PAGE_SIZE >> 1) << 3 allocates 16348 channels 314 */ 315#define HV_MAX_NUM_CHANNELS (PAGE_SIZE >> 1) << 3 316 317/* 318 * (The value here must be in multiple of 32) 319 */ 320#define HV_MAX_NUM_CHANNELS_SUPPORTED 256 321 322/* 323 * VM Bus connection states 324 */ 325typedef enum { 326 HV_DISCONNECTED, 327 HV_CONNECTING, 328 HV_CONNECTED, 329 HV_DISCONNECTING 330} hv_vmbus_connect_state; 331 332#define HV_MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT 333 334 335typedef struct { 336 hv_vmbus_connect_state connect_state; 337 uint32_t next_gpadl_handle; 338 /** 339 * Represents channel interrupts. Each bit position 340 * represents a channel. 341 * When a channel sends an interrupt via VMBUS, it 342 * finds its bit in the send_interrupt_page, set it and 343 * calls Hv to generate a port event. The other end 344 * receives the port event and parse the 345 * recv_interrupt_page to see which bit is set 346 */ 347 void *interrupt_page; 348 void *send_interrupt_page; 349 void *recv_interrupt_page; 350 /* 351 * 2 pages - 1st page for parent->child 352 * notification and 2nd is child->parent 353 * notification 354 */ 355 void *monitor_pages; 356 TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor; 357 struct mtx channel_msg_lock; 358 /** 359 * List of primary channels. Sub channels will be linked 360 * under their primary channel. 361 */ 362 TAILQ_HEAD(, hv_vmbus_channel) channel_anchor; 363 struct mtx channel_lock; 364 365 /** 366 * channel table for fast lookup through id. 367 */ 368 hv_vmbus_channel **channels; 369 hv_vmbus_handle work_queue; 370 struct sema control_sema; 371} hv_vmbus_connection; 372 373typedef union { 374 uint64_t as_uint64_t; 375 struct { 376 uint64_t build_number : 16; 377 uint64_t service_version : 8; /* Service Pack, etc. */ 378 uint64_t minor_version : 8; 379 uint64_t major_version : 8; 380 /* 381 * HV_GUEST_OS_MICROSOFT_IDS (If Vendor=MS) 382 * HV_GUEST_OS_VENDOR 383 */ 384 uint64_t os_id : 8; 385 uint64_t vendor_id : 16; 386 } u; 387} hv_vmbus_x64_msr_guest_os_id_contents; 388 389 390typedef union { 391 uint64_t as_uint64_t; 392 struct { 393 uint64_t enable :1; 394 uint64_t reserved :11; 395 uint64_t guest_physical_address :52; 396 } u; 397} hv_vmbus_x64_msr_hypercall_contents; 398 399typedef union { 400 uint32_t as_uint32_t; 401 struct { 402 uint32_t group_enable :4; 403 uint32_t rsvd_z :28; 404 } u; 405} hv_vmbus_monitor_trigger_state; 406 407typedef union { 408 uint64_t as_uint64_t; 409 struct { 410 uint32_t pending; 411 uint32_t armed; 412 } u; 413} hv_vmbus_monitor_trigger_group; 414 415typedef struct { 416 hv_vmbus_connection_id connection_id; 417 uint16_t flag_number; 418 uint16_t rsvd_z; 419} hv_vmbus_monitor_parameter; 420 421/* 422 * hv_vmbus_monitor_page Layout 423 * ------------------------------------------------------ 424 * | 0 | trigger_state (4 bytes) | Rsvd1 (4 bytes) | 425 * | 8 | trigger_group[0] | 426 * | 10 | trigger_group[1] | 427 * | 18 | trigger_group[2] | 428 * | 20 | trigger_group[3] | 429 * | 28 | Rsvd2[0] | 430 * | 30 | Rsvd2[1] | 431 * | 38 | Rsvd2[2] | 432 * | 40 | next_check_time[0][0] | next_check_time[0][1] | 433 * | ... | 434 * | 240 | latency[0][0..3] | 435 * | 340 | Rsvz3[0] | 436 * | 440 | parameter[0][0] | 437 * | 448 | parameter[0][1] | 438 * | ... | 439 * | 840 | Rsvd4[0] | 440 * ------------------------------------------------------ 441 */ 442 443typedef struct { 444 hv_vmbus_monitor_trigger_state trigger_state; 445 uint32_t rsvd_z1; 446 447 hv_vmbus_monitor_trigger_group trigger_group[4]; 448 uint64_t rsvd_z2[3]; 449 450 int32_t next_check_time[4][32]; 451 452 uint16_t latency[4][32]; 453 uint64_t rsvd_z3[32]; 454 455 hv_vmbus_monitor_parameter parameter[4][32]; 456 457 uint8_t rsvd_z4[1984]; 458} hv_vmbus_monitor_page; 459 460/* 461 * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent 462 * is set by CPUID(HV_CPU_ID_FUNCTION_VERSION_AND_FEATURES). 463 */ 464typedef enum { 465 HV_CPU_ID_FUNCTION_VERSION_AND_FEATURES = 0x00000001, 466 HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION = 0x40000000, 467 HV_CPU_ID_FUNCTION_HV_INTERFACE = 0x40000001, 468 /* 469 * The remaining functions depend on the value 470 * of hv_cpu_id_function_interface 471 */ 472 HV_CPU_ID_FUNCTION_MS_HV_VERSION = 0x40000002, 473 HV_CPU_ID_FUNCTION_MS_HV_FEATURES = 0x40000003, 474 HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION = 0x40000004, 475 HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005, 476 HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE = 0x40000006 477} hv_vmbus_cpuid_function; 478 479#define HV_FEATURE_MSR_TIME_REFCNT (1 << 1) 480#define HV_FEATURE_MSR_SYNCIC (1 << 2) 481#define HV_FEATURE_MSR_STIMER (1 << 3) 482#define HV_FEATURE_MSR_APIC (1 << 4) 483#define HV_FEATURE_MSR_HYPERCALL (1 << 5) 484#define HV_FEATURE_MSR_GUEST_IDLE (1 << 10) 485 486/* 487 * Define the format of the SIMP register 488 */ 489typedef union { 490 uint64_t as_uint64_t; 491 struct { 492 uint64_t simp_enabled : 1; 493 uint64_t preserved : 11; 494 uint64_t base_simp_gpa : 52; 495 } u; 496} hv_vmbus_synic_simp; 497 498/* 499 * Define the format of the SIEFP register 500 */ 501typedef union { 502 uint64_t as_uint64_t; 503 struct { 504 uint64_t siefp_enabled : 1; 505 uint64_t preserved : 11; 506 uint64_t base_siefp_gpa : 52; 507 } u; 508} hv_vmbus_synic_siefp; 509 510/* 511 * Define synthetic interrupt source 512 */ 513typedef union { 514 uint64_t as_uint64_t; 515 struct { 516 uint64_t vector : 8; 517 uint64_t reserved1 : 8; 518 uint64_t masked : 1; 519 uint64_t auto_eoi : 1; 520 uint64_t reserved2 : 46; 521 } u; 522} hv_vmbus_synic_sint; 523 524/* 525 * Timer configuration register. 526 */ 527union hv_timer_config { 528 uint64_t as_uint64; 529 struct { 530 uint64_t enable:1; 531 uint64_t periodic:1; 532 uint64_t lazy:1; 533 uint64_t auto_enable:1; 534 uint64_t reserved_z0:12; 535 uint64_t sintx:4; 536 uint64_t reserved_z1:44; 537 }; 538}; 539 540/* 541 * Define syn_ic control register 542 */ 543typedef union _hv_vmbus_synic_scontrol { 544 uint64_t as_uint64_t; 545 struct { 546 uint64_t enable : 1; 547 uint64_t reserved : 63; 548 } u; 549} hv_vmbus_synic_scontrol; 550 551/* 552 * Define the hv_vmbus_post_message hypercall input structure 553 */ 554typedef struct { 555 hv_vmbus_connection_id connection_id; 556 uint32_t reserved; 557 hv_vmbus_msg_type message_type; 558 uint32_t payload_size; 559 uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; 560} hv_vmbus_input_post_message; 561 562/* 563 * Define the synthetic interrupt controller event flags format 564 */ 565typedef union { 566 uint8_t flags8[HV_EVENT_FLAGS_BYTE_COUNT]; 567 uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT]; 568} hv_vmbus_synic_event_flags; 569 570#define HV_X64_CPUID_MIN (0x40000005) 571#define HV_X64_CPUID_MAX (0x4000ffff) 572 573/* 574 * Declare the MSR used to identify the guest OS 575 */ 576#define HV_X64_MSR_GUEST_OS_ID (0x40000000) 577/* 578 * Declare the MSR used to setup pages used to communicate with the hypervisor 579 */ 580#define HV_X64_MSR_HYPERCALL (0x40000001) 581/* MSR used to provide vcpu index */ 582#define HV_X64_MSR_VP_INDEX (0x40000002) 583 584#define HV_X64_MSR_TIME_REF_COUNT (0x40000020) 585 586/* 587 * Define synthetic interrupt controller model specific registers 588 */ 589#define HV_X64_MSR_SCONTROL (0x40000080) 590#define HV_X64_MSR_SVERSION (0x40000081) 591#define HV_X64_MSR_SIEFP (0x40000082) 592#define HV_X64_MSR_SIMP (0x40000083) 593#define HV_X64_MSR_EOM (0x40000084) 594 595#define HV_X64_MSR_SINT0 (0x40000090) 596#define HV_X64_MSR_SINT1 (0x40000091) 597#define HV_X64_MSR_SINT2 (0x40000092) 598#define HV_X64_MSR_SINT3 (0x40000093) 599#define HV_X64_MSR_SINT4 (0x40000094) 600#define HV_X64_MSR_SINT5 (0x40000095) 601#define HV_X64_MSR_SINT6 (0x40000096) 602#define HV_X64_MSR_SINT7 (0x40000097) 603#define HV_X64_MSR_SINT8 (0x40000098) 604#define HV_X64_MSR_SINT9 (0x40000099) 605#define HV_X64_MSR_SINT10 (0x4000009A) 606#define HV_X64_MSR_SINT11 (0x4000009B) 607#define HV_X64_MSR_SINT12 (0x4000009C) 608#define HV_X64_MSR_SINT13 (0x4000009D) 609#define HV_X64_MSR_SINT14 (0x4000009E) 610#define HV_X64_MSR_SINT15 (0x4000009F) 611 612/* 613 * Synthetic Timer MSRs. Four timers per vcpu. 614 */ 615#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0 616#define HV_X64_MSR_STIMER0_COUNT 0x400000B1 617#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2 618#define HV_X64_MSR_STIMER1_COUNT 0x400000B3 619#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4 620#define HV_X64_MSR_STIMER2_COUNT 0x400000B5 621#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6 622#define HV_X64_MSR_STIMER3_COUNT 0x400000B7 623 624/* 625 * Declare the various hypercall operations 626 */ 627typedef enum { 628 HV_CALL_POST_MESSAGE = 0x005c, 629 HV_CALL_SIGNAL_EVENT = 0x005d, 630} hv_vmbus_call_code; 631 632/** 633 * Global variables 634 */ 635 636extern hv_vmbus_context hv_vmbus_g_context; 637extern hv_vmbus_connection hv_vmbus_g_connection; 638 639extern u_int hyperv_features; 640extern u_int hyperv_recommends; 641 642typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg); 643 644typedef struct hv_vmbus_channel_msg_table_entry { 645 hv_vmbus_channel_msg_type messageType; 646 647 bool handler_no_sleep; /* true: the handler doesn't sleep */ 648 vmbus_msg_handler messageHandler; 649} hv_vmbus_channel_msg_table_entry; 650 651extern hv_vmbus_channel_msg_table_entry g_channel_message_table[]; 652 653/* 654 * Private, VM Bus functions 655 */ 656 657int hv_vmbus_ring_buffer_init( 658 hv_vmbus_ring_buffer_info *ring_info, 659 void *buffer, 660 uint32_t buffer_len); 661 662void hv_ring_buffer_cleanup( 663 hv_vmbus_ring_buffer_info *ring_info); 664 665int hv_ring_buffer_write( 666 hv_vmbus_ring_buffer_info *ring_info, 667 hv_vmbus_sg_buffer_list sg_buffers[], 668 uint32_t sg_buff_count, 669 boolean_t *need_sig); 670 671int hv_ring_buffer_peek( 672 hv_vmbus_ring_buffer_info *ring_info, 673 void *buffer, 674 uint32_t buffer_len); 675 676int hv_ring_buffer_read( 677 hv_vmbus_ring_buffer_info *ring_info, 678 void *buffer, 679 uint32_t buffer_len, 680 uint32_t offset); 681 682uint32_t hv_vmbus_get_ring_buffer_interrupt_mask( 683 hv_vmbus_ring_buffer_info *ring_info); 684 685void hv_vmbus_dump_ring_info( 686 hv_vmbus_ring_buffer_info *ring_info, 687 char *prefix); 688 689void hv_ring_buffer_read_begin( 690 hv_vmbus_ring_buffer_info *ring_info); 691 692uint32_t hv_ring_buffer_read_end( 693 hv_vmbus_ring_buffer_info *ring_info); 694 695hv_vmbus_channel* hv_vmbus_allocate_channel(void); 696void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel); 697void hv_vmbus_on_channel_message(void *context); 698int hv_vmbus_request_channel_offers(void); 699void hv_vmbus_release_unattached_channels(void); 700int hv_vmbus_init(void); 701void hv_vmbus_cleanup(void); 702 703uint16_t hv_vmbus_post_msg_via_msg_ipc( 704 hv_vmbus_connection_id connection_id, 705 hv_vmbus_msg_type message_type, 706 void *payload, 707 size_t payload_size); 708 709uint16_t hv_vmbus_signal_event(void *con_id); 710void hv_vmbus_synic_init(void *irq_arg); 711void hv_vmbus_synic_cleanup(void *arg); 712int hv_vmbus_query_hypervisor_presence(void); 713 714struct hv_device* hv_vmbus_child_device_create( 715 hv_guid device_type, 716 hv_guid device_instance, 717 hv_vmbus_channel *channel); 718 719int hv_vmbus_child_device_register( 720 struct hv_device *child_dev); 721int hv_vmbus_child_device_unregister( 722 struct hv_device *child_dev); 723 724/** 725 * Connection interfaces 726 */ 727int hv_vmbus_connect(void); 728int hv_vmbus_disconnect(void); 729int hv_vmbus_post_message(void *buffer, size_t buf_size); 730int hv_vmbus_set_event(hv_vmbus_channel *channel); 731void hv_vmbus_on_events(void *); 732 733/** 734 * Event Timer interfaces 735 */ 736void hv_et_init(void); 737void hv_et_intr(struct trapframe*); 738 739/* 740 * The guest OS needs to register the guest ID with the hypervisor. 741 * The guest ID is a 64 bit entity and the structure of this ID is 742 * specified in the Hyper-V specification: 743 * 744 * http://msdn.microsoft.com/en-us/library/windows/ 745 * hardware/ff542653%28v=vs.85%29.aspx 746 * 747 * While the current guideline does not specify how FreeBSD guest ID(s) 748 * need to be generated, our plan is to publish the guidelines for 749 * FreeBSD and other guest operating systems that currently are hosted 750 * on Hyper-V. The implementation here conforms to this yet 751 * unpublished guidelines. 752 * 753 * Bit(s) 754 * 63 - Indicates if the OS is Open Source or not; 1 is Open Source 755 * 62:56 - Os Type; Linux is 0x100, FreeBSD is 0x200 756 * 55:48 - Distro specific identification 757 * 47:16 - FreeBSD kernel version number 758 * 15:0 - Distro specific identification 759 * 760 */ 761 762#define HV_FREEBSD_VENDOR_ID 0x8200 763#define HV_FREEBSD_GUEST_ID hv_generate_guest_id(0,0) 764 765static inline uint64_t hv_generate_guest_id( 766 uint8_t distro_id_part1, 767 uint16_t distro_id_part2) 768{ 769 uint64_t guest_id; 770 guest_id = (((uint64_t)HV_FREEBSD_VENDOR_ID) << 48); 771 guest_id |= (((uint64_t)(distro_id_part1)) << 48); 772 guest_id |= (((uint64_t)(__FreeBSD_version)) << 16); /* in param.h */ 773 guest_id |= ((uint64_t)(distro_id_part2)); 774 return guest_id; 775} 776 777typedef struct { 778 unsigned int vector; 779 void *page_buffers[2 * MAXCPU]; 780} hv_setup_args; 781 782#endif /* __HYPERV_PRIV_H__ */ 783