|  | /* | 
|  | * | 
|  | * Copyright (c) 2011, Microsoft Corporation. | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or modify it | 
|  | * under the terms and conditions of the GNU General Public License, | 
|  | * version 2, as published by the Free Software Foundation. | 
|  | * | 
|  | * This program is distributed in the hope it will be useful, but WITHOUT | 
|  | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|  | * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | 
|  | * more details. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License along with | 
|  | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 
|  | * Place - Suite 330, Boston, MA 02111-1307 USA. | 
|  | * | 
|  | * Authors: | 
|  | *   Haiyang Zhang <haiyangz@microsoft.com> | 
|  | *   Hank Janssen  <hjanssen@microsoft.com> | 
|  | *   K. Y. Srinivasan <kys@microsoft.com> | 
|  | * | 
|  | */ | 
|  |  | 
|  | #ifndef _HYPERV_VMBUS_H | 
|  | #define _HYPERV_VMBUS_H | 
|  |  | 
|  | #include <linux/list.h> | 
|  | #include <asm/sync_bitops.h> | 
|  | #include <linux/atomic.h> | 
|  | #include <linux/hyperv.h> | 
|  |  | 
|  | /* | 
|  | * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent | 
|  | * is set by CPUID(HVCPUID_VERSION_FEATURES). | 
|  | */ | 
|  | enum hv_cpuid_function { | 
|  | HVCPUID_VERSION_FEATURES		= 0x00000001, | 
|  | HVCPUID_VENDOR_MAXFUNCTION		= 0x40000000, | 
|  | HVCPUID_INTERFACE			= 0x40000001, | 
|  |  | 
|  | /* | 
|  | * The remaining functions depend on the value of | 
|  | * HVCPUID_INTERFACE | 
|  | */ | 
|  | HVCPUID_VERSION			= 0x40000002, | 
|  | HVCPUID_FEATURES			= 0x40000003, | 
|  | HVCPUID_ENLIGHTENMENT_INFO	= 0x40000004, | 
|  | HVCPUID_IMPLEMENTATION_LIMITS		= 0x40000005, | 
|  | }; | 
|  |  | 
|  | /* Define version of the synthetic interrupt controller. */ | 
|  | #define HV_SYNIC_VERSION		(1) | 
|  |  | 
|  | /* Define the expected SynIC version. */ | 
|  | #define HV_SYNIC_VERSION_1		(0x1) | 
|  |  | 
|  | /* Define synthetic interrupt controller message constants. */ | 
|  | #define HV_MESSAGE_SIZE			(256) | 
|  | #define HV_MESSAGE_PAYLOAD_BYTE_COUNT	(240) | 
|  | #define HV_MESSAGE_PAYLOAD_QWORD_COUNT	(30) | 
|  | #define HV_ANY_VP			(0xFFFFFFFF) | 
|  |  | 
|  | /* Define synthetic interrupt controller flag constants. */ | 
|  | #define HV_EVENT_FLAGS_COUNT		(256 * 8) | 
|  | #define HV_EVENT_FLAGS_BYTE_COUNT	(256) | 
|  | #define HV_EVENT_FLAGS_DWORD_COUNT	(256 / sizeof(u32)) | 
|  |  | 
|  | /* Define hypervisor message types. */ | 
|  | enum hv_message_type { | 
|  | HVMSG_NONE			= 0x00000000, | 
|  |  | 
|  | /* Memory access messages. */ | 
|  | HVMSG_UNMAPPED_GPA		= 0x80000000, | 
|  | HVMSG_GPA_INTERCEPT		= 0x80000001, | 
|  |  | 
|  | /* Timer notification messages. */ | 
|  | HVMSG_TIMER_EXPIRED			= 0x80000010, | 
|  |  | 
|  | /* Error messages. */ | 
|  | HVMSG_INVALID_VP_REGISTER_VALUE	= 0x80000020, | 
|  | HVMSG_UNRECOVERABLE_EXCEPTION	= 0x80000021, | 
|  | HVMSG_UNSUPPORTED_FEATURE		= 0x80000022, | 
|  |  | 
|  | /* Trace buffer complete messages. */ | 
|  | HVMSG_EVENTLOG_BUFFERCOMPLETE	= 0x80000040, | 
|  |  | 
|  | /* Platform-specific processor intercept messages. */ | 
|  | HVMSG_X64_IOPORT_INTERCEPT		= 0x80010000, | 
|  | HVMSG_X64_MSR_INTERCEPT		= 0x80010001, | 
|  | HVMSG_X64_CPUID_INTERCEPT		= 0x80010002, | 
|  | HVMSG_X64_EXCEPTION_INTERCEPT	= 0x80010003, | 
|  | HVMSG_X64_APIC_EOI			= 0x80010004, | 
|  | HVMSG_X64_LEGACY_FP_ERROR		= 0x80010005 | 
|  | }; | 
|  |  | 
|  | /* Define the number of synthetic interrupt sources. */ | 
|  | #define HV_SYNIC_SINT_COUNT		(16) | 
|  | #define HV_SYNIC_STIMER_COUNT		(4) | 
|  |  | 
|  | /* Define invalid partition identifier. */ | 
|  | #define HV_PARTITION_ID_INVALID		((u64)0x0) | 
|  |  | 
|  | /* Define connection identifier type. */ | 
|  | union hv_connection_id { | 
|  | u32 asu32; | 
|  | struct { | 
|  | u32 id:24; | 
|  | u32 reserved:8; | 
|  | } u; | 
|  | }; | 
|  |  | 
|  | /* Define port identifier type. */ | 
|  | union hv_port_id { | 
|  | u32 asu32; | 
|  | struct { | 
|  | u32 id:24; | 
|  | u32 reserved:8; | 
|  | } u ; | 
|  | }; | 
|  |  | 
|  | /* Define port type. */ | 
|  | enum hv_port_type { | 
|  | HVPORT_MSG	= 1, | 
|  | HVPORT_EVENT		= 2, | 
|  | HVPORT_MONITOR	= 3 | 
|  | }; | 
|  |  | 
|  | /* Define port information structure. */ | 
|  | struct hv_port_info { | 
|  | enum hv_port_type port_type; | 
|  | u32 padding; | 
|  | union { | 
|  | struct { | 
|  | u32 target_sint; | 
|  | u32 target_vp; | 
|  | u64 rsvdz; | 
|  | } message_port_info; | 
|  | struct { | 
|  | u32 target_sint; | 
|  | u32 target_vp; | 
|  | u16 base_flag_bumber; | 
|  | u16 flag_count; | 
|  | u32 rsvdz; | 
|  | } event_port_info; | 
|  | struct { | 
|  | u64 monitor_address; | 
|  | u64 rsvdz; | 
|  | } monitor_port_info; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | struct hv_connection_info { | 
|  | enum hv_port_type port_type; | 
|  | u32 padding; | 
|  | union { | 
|  | struct { | 
|  | u64 rsvdz; | 
|  | } message_connection_info; | 
|  | struct { | 
|  | u64 rsvdz; | 
|  | } event_connection_info; | 
|  | struct { | 
|  | u64 monitor_address; | 
|  | } monitor_connection_info; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Define synthetic interrupt controller message flags. */ | 
|  | union hv_message_flags { | 
|  | u8 asu8; | 
|  | struct { | 
|  | u8 msg_pending:1; | 
|  | u8 reserved:7; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Define synthetic interrupt controller message header. */ | 
|  | struct hv_message_header { | 
|  | enum hv_message_type message_type; | 
|  | u8 payload_size; | 
|  | union hv_message_flags message_flags; | 
|  | u8 reserved[2]; | 
|  | union { | 
|  | u64 sender; | 
|  | union hv_port_id port; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Define timer message payload structure. */ | 
|  | struct hv_timer_message_payload { | 
|  | u32 timer_index; | 
|  | u32 reserved; | 
|  | u64 expiration_time;	/* When the timer expired */ | 
|  | u64 delivery_time;	/* When the message was delivered */ | 
|  | }; | 
|  |  | 
|  | /* Define synthetic interrupt controller message format. */ | 
|  | struct hv_message { | 
|  | struct hv_message_header header; | 
|  | union { | 
|  | u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; | 
|  | } u ; | 
|  | }; | 
|  |  | 
|  | /* Define the number of message buffers associated with each port. */ | 
|  | #define HV_PORT_MESSAGE_BUFFER_COUNT	(16) | 
|  |  | 
|  | /* Define the synthetic interrupt message page layout. */ | 
|  | struct hv_message_page { | 
|  | struct hv_message sint_message[HV_SYNIC_SINT_COUNT]; | 
|  | }; | 
|  |  | 
|  | /* Define the synthetic interrupt controller event flags format. */ | 
|  | union hv_synic_event_flags { | 
|  | u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT]; | 
|  | u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT]; | 
|  | }; | 
|  |  | 
|  | /* Define the synthetic interrupt flags page layout. */ | 
|  | struct hv_synic_event_flags_page { | 
|  | union hv_synic_event_flags sintevent_flags[HV_SYNIC_SINT_COUNT]; | 
|  | }; | 
|  |  | 
|  | /* Define SynIC control register. */ | 
|  | union hv_synic_scontrol { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u64 enable:1; | 
|  | u64 reserved:63; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Define synthetic interrupt source. */ | 
|  | union hv_synic_sint { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u64 vector:8; | 
|  | u64 reserved1:8; | 
|  | u64 masked:1; | 
|  | u64 auto_eoi:1; | 
|  | u64 reserved2:46; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Define the format of the SIMP register */ | 
|  | union hv_synic_simp { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u64 simp_enabled:1; | 
|  | u64 preserved:11; | 
|  | u64 base_simp_gpa:52; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Define the format of the SIEFP register */ | 
|  | union hv_synic_siefp { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u64 siefp_enabled:1; | 
|  | u64 preserved:11; | 
|  | u64 base_siefp_gpa:52; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Definitions for the monitored notification facility */ | 
|  | union hv_monitor_trigger_group { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u32 pending; | 
|  | u32 armed; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | struct hv_monitor_parameter { | 
|  | union hv_connection_id connectionid; | 
|  | u16 flagnumber; | 
|  | u16 rsvdz; | 
|  | }; | 
|  |  | 
|  | union hv_monitor_trigger_state { | 
|  | u32 asu32; | 
|  |  | 
|  | struct { | 
|  | u32 group_enable:4; | 
|  | u32 rsvdz:28; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* struct hv_monitor_page Layout */ | 
|  | /* ------------------------------------------------------ */ | 
|  | /* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */ | 
|  | /* | 8   | TriggerGroup[0]                              | */ | 
|  | /* | 10  | TriggerGroup[1]                              | */ | 
|  | /* | 18  | TriggerGroup[2]                              | */ | 
|  | /* | 20  | TriggerGroup[3]                              | */ | 
|  | /* | 28  | Rsvd2[0]                                     | */ | 
|  | /* | 30  | Rsvd2[1]                                     | */ | 
|  | /* | 38  | Rsvd2[2]                                     | */ | 
|  | /* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */ | 
|  | /* | ...                                                | */ | 
|  | /* | 240 | Latency[0][0..3]                             | */ | 
|  | /* | 340 | Rsvz3[0]                                     | */ | 
|  | /* | 440 | Parameter[0][0]                              | */ | 
|  | /* | 448 | Parameter[0][1]                              | */ | 
|  | /* | ...                                                | */ | 
|  | /* | 840 | Rsvd4[0]                                     | */ | 
|  | /* ------------------------------------------------------ */ | 
|  | struct hv_monitor_page { | 
|  | union hv_monitor_trigger_state trigger_state; | 
|  | u32 rsvdz1; | 
|  |  | 
|  | union hv_monitor_trigger_group trigger_group[4]; | 
|  | u64 rsvdz2[3]; | 
|  |  | 
|  | s32 next_checktime[4][32]; | 
|  |  | 
|  | u16 latency[4][32]; | 
|  | u64 rsvdz3[32]; | 
|  |  | 
|  | struct hv_monitor_parameter parameter[4][32]; | 
|  |  | 
|  | u8 rsvdz4[1984]; | 
|  | }; | 
|  |  | 
|  | /* Declare the various hypercall operations. */ | 
|  | enum hv_call_code { | 
|  | HVCALL_POST_MESSAGE	= 0x005c, | 
|  | HVCALL_SIGNAL_EVENT	= 0x005d, | 
|  | }; | 
|  |  | 
|  | /* Definition of the hv_post_message hypercall input structure. */ | 
|  | struct hv_input_post_message { | 
|  | union hv_connection_id connectionid; | 
|  | u32 reserved; | 
|  | enum hv_message_type message_type; | 
|  | u32 payload_size; | 
|  | u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; | 
|  | }; | 
|  |  | 
|  | /* Definition of the hv_signal_event hypercall input structure. */ | 
|  | struct hv_input_signal_event { | 
|  | union hv_connection_id connectionid; | 
|  | u16 flag_number; | 
|  | u16 rsvdz; | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Versioning definitions used for guests reporting themselves to the | 
|  | * hypervisor, and visa versa. | 
|  | */ | 
|  |  | 
|  | /* Version info reported by guest OS's */ | 
|  | enum hv_guest_os_vendor { | 
|  | HVGUESTOS_VENDOR_MICROSOFT	= 0x0001 | 
|  | }; | 
|  |  | 
|  | enum hv_guest_os_microsoft_ids { | 
|  | HVGUESTOS_MICROSOFT_UNDEFINED	= 0x00, | 
|  | HVGUESTOS_MICROSOFT_MSDOS		= 0x01, | 
|  | HVGUESTOS_MICROSOFT_WINDOWS3X	= 0x02, | 
|  | HVGUESTOS_MICROSOFT_WINDOWS9X	= 0x03, | 
|  | HVGUESTOS_MICROSOFT_WINDOWSNT	= 0x04, | 
|  | HVGUESTOS_MICROSOFT_WINDOWSCE	= 0x05 | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Declare the MSR used to identify the guest OS. | 
|  | */ | 
|  | #define HV_X64_MSR_GUEST_OS_ID	0x40000000 | 
|  |  | 
|  | union hv_x64_msr_guest_os_id_contents { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u64 build_number:16; | 
|  | u64 service_version:8; /* Service Pack, etc. */ | 
|  | u64 minor_version:8; | 
|  | u64 major_version:8; | 
|  | u64 os_id:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */ | 
|  | u64 vendor_id:16; /* enum hv_guest_os_vendor */ | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Declare the MSR used to setup pages used to communicate with the hypervisor. | 
|  | */ | 
|  | #define HV_X64_MSR_HYPERCALL	0x40000001 | 
|  |  | 
|  | union hv_x64_msr_hypercall_contents { | 
|  | u64 as_uint64; | 
|  | struct { | 
|  | u64 enable:1; | 
|  | u64 reserved:11; | 
|  | u64 guest_physical_address:52; | 
|  | }; | 
|  | }; | 
|  |  | 
|  |  | 
|  | enum { | 
|  | VMBUS_MESSAGE_CONNECTION_ID	= 1, | 
|  | VMBUS_MESSAGE_PORT_ID		= 1, | 
|  | VMBUS_EVENT_CONNECTION_ID	= 2, | 
|  | VMBUS_EVENT_PORT_ID		= 2, | 
|  | VMBUS_MONITOR_CONNECTION_ID	= 3, | 
|  | VMBUS_MONITOR_PORT_ID		= 3, | 
|  | VMBUS_MESSAGE_SINT		= 2, | 
|  | }; | 
|  |  | 
|  | /* #defines */ | 
|  |  | 
|  | #define HV_PRESENT_BIT			0x80000000 | 
|  |  | 
|  | #define HV_LINUX_GUEST_ID_LO		0x00000000 | 
|  | #define HV_LINUX_GUEST_ID_HI		0xB16B00B5 | 
|  | #define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \ | 
|  | HV_LINUX_GUEST_ID_LO) | 
|  |  | 
|  | #define HV_CPU_POWER_MANAGEMENT		(1 << 0) | 
|  | #define HV_RECOMMENDATIONS_MAX		4 | 
|  |  | 
|  | #define HV_X64_MAX			5 | 
|  | #define HV_CAPS_MAX			8 | 
|  |  | 
|  |  | 
|  | #define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64) | 
|  |  | 
|  |  | 
|  | /* Service definitions */ | 
|  |  | 
|  | #define HV_SERVICE_PARENT_PORT				(0) | 
|  | #define HV_SERVICE_PARENT_CONNECTION			(0) | 
|  |  | 
|  | #define HV_SERVICE_CONNECT_RESPONSE_SUCCESS		(0) | 
|  | #define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER	(1) | 
|  | #define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE	(2) | 
|  | #define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED	(3) | 
|  |  | 
|  | #define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID		(1) | 
|  | #define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID		(2) | 
|  | #define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID	(3) | 
|  | #define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID	(4) | 
|  | #define HV_SERVICE_MAX_MESSAGE_ID				(4) | 
|  |  | 
|  | #define HV_SERVICE_PROTOCOL_VERSION (0x0010) | 
|  | #define HV_CONNECT_PAYLOAD_BYTE_COUNT 64 | 
|  |  | 
|  | /* #define VMBUS_REVISION_NUMBER	6 */ | 
|  |  | 
|  | /* Our local vmbus's port and connection id. Anything >0 is fine */ | 
|  | /* #define VMBUS_PORT_ID		11 */ | 
|  |  | 
|  | /* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */ | 
|  | static const uuid_le VMBUS_SERVICE_ID = { | 
|  | .b = { | 
|  | 0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c, | 
|  | 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4 | 
|  | }, | 
|  | }; | 
|  |  | 
|  | #define MAX_NUM_CPUS	32 | 
|  |  | 
|  |  | 
|  | struct hv_input_signal_event_buffer { | 
|  | u64 align8; | 
|  | struct hv_input_signal_event event; | 
|  | }; | 
|  |  | 
|  | struct hv_context { | 
|  | /* We only support running on top of Hyper-V | 
|  | * So at this point this really can only contain the Hyper-V ID | 
|  | */ | 
|  | u64 guestid; | 
|  |  | 
|  | void *hypercall_page; | 
|  |  | 
|  | bool synic_initialized; | 
|  |  | 
|  | /* | 
|  | * This is used as an input param to HvCallSignalEvent hypercall. The | 
|  | * input param is immutable in our usage and must be dynamic mem (vs | 
|  | * stack or global). */ | 
|  | struct hv_input_signal_event_buffer *signal_event_buffer; | 
|  | /* 8-bytes aligned of the buffer above */ | 
|  | struct hv_input_signal_event *signal_event_param; | 
|  |  | 
|  | void *synic_message_page[MAX_NUM_CPUS]; | 
|  | void *synic_event_page[MAX_NUM_CPUS]; | 
|  | }; | 
|  |  | 
|  | extern struct hv_context hv_context; | 
|  |  | 
|  |  | 
|  | /* Hv Interface */ | 
|  |  | 
|  | extern int hv_init(void); | 
|  |  | 
|  | extern void hv_cleanup(void); | 
|  |  | 
|  | extern u16 hv_post_message(union hv_connection_id connection_id, | 
|  | enum hv_message_type message_type, | 
|  | void *payload, size_t payload_size); | 
|  |  | 
|  | extern u16 hv_signal_event(void); | 
|  |  | 
|  | extern void hv_synic_init(void *irqarg); | 
|  |  | 
|  | extern void hv_synic_cleanup(void *arg); | 
|  |  | 
|  |  | 
|  | /* Interface */ | 
|  |  | 
|  |  | 
|  | int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer, | 
|  | u32 buflen); | 
|  |  | 
|  | void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); | 
|  |  | 
|  | int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info, | 
|  | struct scatterlist *sglist, | 
|  | u32 sgcount); | 
|  |  | 
|  | int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer, | 
|  | u32 buflen); | 
|  |  | 
|  | int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info, | 
|  | void *buffer, | 
|  | u32 buflen, | 
|  | u32 offset); | 
|  |  | 
|  | u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info); | 
|  |  | 
|  | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, | 
|  | struct hv_ring_buffer_debug_info *debug_info); | 
|  |  | 
|  | /* | 
|  | * Maximum channels is determined by the size of the interrupt page | 
|  | * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt | 
|  | * and the other is receive endpoint interrupt | 
|  | */ | 
|  | #define MAX_NUM_CHANNELS	((PAGE_SIZE >> 1) << 3)	/* 16348 channels */ | 
|  |  | 
|  | /* The value here must be in multiple of 32 */ | 
|  | /* TODO: Need to make this configurable */ | 
|  | #define MAX_NUM_CHANNELS_SUPPORTED	256 | 
|  |  | 
|  |  | 
|  | enum vmbus_connect_state { | 
|  | DISCONNECTED, | 
|  | CONNECTING, | 
|  | CONNECTED, | 
|  | DISCONNECTING | 
|  | }; | 
|  |  | 
|  | #define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT | 
|  |  | 
|  | struct vmbus_connection { | 
|  | enum vmbus_connect_state conn_state; | 
|  |  | 
|  | atomic_t next_gpadl_handle; | 
|  |  | 
|  | /* | 
|  | * Represents channel interrupts. Each bit position represents a | 
|  | * channel.  When a channel sends an interrupt via VMBUS, it finds its | 
|  | * bit in the sendInterruptPage, set it and calls Hv to generate a port | 
|  | * event. The other end receives the port event and parse the | 
|  | * recvInterruptPage to see which bit is set | 
|  | */ | 
|  | void *int_page; | 
|  | void *send_int_page; | 
|  | void *recv_int_page; | 
|  |  | 
|  | /* | 
|  | * 2 pages - 1st page for parent->child notification and 2nd | 
|  | * is child->parent notification | 
|  | */ | 
|  | void *monitor_pages; | 
|  | struct list_head chn_msg_list; | 
|  | spinlock_t channelmsg_lock; | 
|  |  | 
|  | /* List of channels */ | 
|  | struct list_head chn_list; | 
|  | spinlock_t channel_lock; | 
|  |  | 
|  | struct workqueue_struct *work_queue; | 
|  | }; | 
|  |  | 
|  |  | 
|  | struct vmbus_msginfo { | 
|  | /* Bookkeeping stuff */ | 
|  | struct list_head msglist_entry; | 
|  |  | 
|  | /* The message itself */ | 
|  | unsigned char msg[0]; | 
|  | }; | 
|  |  | 
|  |  | 
|  | extern struct vmbus_connection vmbus_connection; | 
|  |  | 
|  | /* General vmbus interface */ | 
|  |  | 
|  | struct hv_device *vmbus_device_create(uuid_le *type, | 
|  | uuid_le *instance, | 
|  | struct vmbus_channel *channel); | 
|  |  | 
|  | int vmbus_device_register(struct hv_device *child_device_obj); | 
|  | void vmbus_device_unregister(struct hv_device *device_obj); | 
|  |  | 
|  | /* static void */ | 
|  | /* VmbusChildDeviceDestroy( */ | 
|  | /* struct hv_device *); */ | 
|  |  | 
|  | struct vmbus_channel *relid2channel(u32 relid); | 
|  |  | 
|  |  | 
|  | /* Connection interface */ | 
|  |  | 
|  | int vmbus_connect(void); | 
|  |  | 
|  | int vmbus_post_msg(void *buffer, size_t buflen); | 
|  |  | 
|  | int vmbus_set_event(u32 child_relid); | 
|  |  | 
|  | void vmbus_on_event(unsigned long data); | 
|  |  | 
|  |  | 
|  | #endif /* _HYPERV_VMBUS_H */ |