aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/hyperv_vmbus.h
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-10-04 15:29:52 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-11 00:52:55 -0400
commit46a971913611a23478283931460a95be962ce329 (patch)
tree7452d0f07ee9f1f5270a8da6c1387f35c439843d /drivers/hv/hyperv_vmbus.h
parent715a4801e734ea9c8e528265ce3ff6aead85bce1 (diff)
Staging: hv: move hyperv code out of staging directory
After many years wandering the desert, it is finally time for the Microsoft HyperV code to move out of the staging directory. Or at least the core hyperv bus code, and the utility driver, the rest still have some review to get through by the various subsystem maintainers. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Diffstat (limited to 'drivers/hv/hyperv_vmbus.h')
-rw-r--r--drivers/hv/hyperv_vmbus.h628
1 files changed, 628 insertions, 0 deletions
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
new file mode 100644
index 000000000000..8261cb64931b
--- /dev/null
+++ b/drivers/hv/hyperv_vmbus.h
@@ -0,0 +1,628 @@
1/*
2 *
3 * Copyright (c) 2011, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 * K. Y. Srinivasan <kys@microsoft.com>
22 *
23 */
24
25#ifndef _HYPERV_VMBUS_H
26#define _HYPERV_VMBUS_H
27
28#include <linux/list.h>
29#include <asm/sync_bitops.h>
30#include <linux/atomic.h>
31#include <linux/hyperv.h>
32
33/*
34 * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
35 * is set by CPUID(HVCPUID_VERSION_FEATURES).
36 */
37enum hv_cpuid_function {
38 HVCPUID_VERSION_FEATURES = 0x00000001,
39 HVCPUID_VENDOR_MAXFUNCTION = 0x40000000,
40 HVCPUID_INTERFACE = 0x40000001,
41
42 /*
43 * The remaining functions depend on the value of
44 * HVCPUID_INTERFACE
45 */
46 HVCPUID_VERSION = 0x40000002,
47 HVCPUID_FEATURES = 0x40000003,
48 HVCPUID_ENLIGHTENMENT_INFO = 0x40000004,
49 HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005,
50};
51
52/* Define version of the synthetic interrupt controller. */
53#define HV_SYNIC_VERSION (1)
54
55/* Define the expected SynIC version. */
56#define HV_SYNIC_VERSION_1 (0x1)
57
58/* Define synthetic interrupt controller message constants. */
59#define HV_MESSAGE_SIZE (256)
60#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240)
61#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30)
62#define HV_ANY_VP (0xFFFFFFFF)
63
64/* Define synthetic interrupt controller flag constants. */
65#define HV_EVENT_FLAGS_COUNT (256 * 8)
66#define HV_EVENT_FLAGS_BYTE_COUNT (256)
67#define HV_EVENT_FLAGS_DWORD_COUNT (256 / sizeof(u32))
68
69/* Define hypervisor message types. */
70enum hv_message_type {
71 HVMSG_NONE = 0x00000000,
72
73 /* Memory access messages. */
74 HVMSG_UNMAPPED_GPA = 0x80000000,
75 HVMSG_GPA_INTERCEPT = 0x80000001,
76
77 /* Timer notification messages. */
78 HVMSG_TIMER_EXPIRED = 0x80000010,
79
80 /* Error messages. */
81 HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
82 HVMSG_UNRECOVERABLE_EXCEPTION = 0x80000021,
83 HVMSG_UNSUPPORTED_FEATURE = 0x80000022,
84
85 /* Trace buffer complete messages. */
86 HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x80000040,
87
88 /* Platform-specific processor intercept messages. */
89 HVMSG_X64_IOPORT_INTERCEPT = 0x80010000,
90 HVMSG_X64_MSR_INTERCEPT = 0x80010001,
91 HVMSG_X64_CPUID_INTERCEPT = 0x80010002,
92 HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003,
93 HVMSG_X64_APIC_EOI = 0x80010004,
94 HVMSG_X64_LEGACY_FP_ERROR = 0x80010005
95};
96
97/* Define the number of synthetic interrupt sources. */
98#define HV_SYNIC_SINT_COUNT (16)
99#define HV_SYNIC_STIMER_COUNT (4)
100
101/* Define invalid partition identifier. */
102#define HV_PARTITION_ID_INVALID ((u64)0x0)
103
104/* Define connection identifier type. */
105union hv_connection_id {
106 u32 asu32;
107 struct {
108 u32 id:24;
109 u32 reserved:8;
110 } u;
111};
112
113/* Define port identifier type. */
114union hv_port_id {
115 u32 asu32;
116 struct {
117 u32 id:24;
118 u32 reserved:8;
119 } u ;
120};
121
122/* Define port type. */
123enum hv_port_type {
124 HVPORT_MSG = 1,
125 HVPORT_EVENT = 2,
126 HVPORT_MONITOR = 3
127};
128
129/* Define port information structure. */
130struct hv_port_info {
131 enum hv_port_type port_type;
132 u32 padding;
133 union {
134 struct {
135 u32 target_sint;
136 u32 target_vp;
137 u64 rsvdz;
138 } message_port_info;
139 struct {
140 u32 target_sint;
141 u32 target_vp;
142 u16 base_flag_bumber;
143 u16 flag_count;
144 u32 rsvdz;
145 } event_port_info;
146 struct {
147 u64 monitor_address;
148 u64 rsvdz;
149 } monitor_port_info;
150 };
151};
152
153struct hv_connection_info {
154 enum hv_port_type port_type;
155 u32 padding;
156 union {
157 struct {
158 u64 rsvdz;
159 } message_connection_info;
160 struct {
161 u64 rsvdz;
162 } event_connection_info;
163 struct {
164 u64 monitor_address;
165 } monitor_connection_info;
166 };
167};
168
169/* Define synthetic interrupt controller message flags. */
170union hv_message_flags {
171 u8 asu8;
172 struct {
173 u8 msg_pending:1;
174 u8 reserved:7;
175 };
176};
177
178/* Define synthetic interrupt controller message header. */
179struct hv_message_header {
180 enum hv_message_type message_type;
181 u8 payload_size;
182 union hv_message_flags message_flags;
183 u8 reserved[2];
184 union {
185 u64 sender;
186 union hv_port_id port;
187 };
188};
189
190/* Define timer message payload structure. */
191struct hv_timer_message_payload {
192 u32 timer_index;
193 u32 reserved;
194 u64 expiration_time; /* When the timer expired */
195 u64 delivery_time; /* When the message was delivered */
196};
197
198/* Define synthetic interrupt controller message format. */
199struct hv_message {
200 struct hv_message_header header;
201 union {
202 u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
203 } u ;
204};
205
206/* Define the number of message buffers associated with each port. */
207#define HV_PORT_MESSAGE_BUFFER_COUNT (16)
208
209/* Define the synthetic interrupt message page layout. */
210struct hv_message_page {
211 struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
212};
213
214/* Define the synthetic interrupt controller event flags format. */
215union hv_synic_event_flags {
216 u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT];
217 u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT];
218};
219
220/* Define the synthetic interrupt flags page layout. */
221struct hv_synic_event_flags_page {
222 union hv_synic_event_flags sintevent_flags[HV_SYNIC_SINT_COUNT];
223};
224
225/* Define SynIC control register. */
226union hv_synic_scontrol {
227 u64 as_uint64;
228 struct {
229 u64 enable:1;
230 u64 reserved:63;
231 };
232};
233
234/* Define synthetic interrupt source. */
235union hv_synic_sint {
236 u64 as_uint64;
237 struct {
238 u64 vector:8;
239 u64 reserved1:8;
240 u64 masked:1;
241 u64 auto_eoi:1;
242 u64 reserved2:46;
243 };
244};
245
246/* Define the format of the SIMP register */
247union hv_synic_simp {
248 u64 as_uint64;
249 struct {
250 u64 simp_enabled:1;
251 u64 preserved:11;
252 u64 base_simp_gpa:52;
253 };
254};
255
256/* Define the format of the SIEFP register */
257union hv_synic_siefp {
258 u64 as_uint64;
259 struct {
260 u64 siefp_enabled:1;
261 u64 preserved:11;
262 u64 base_siefp_gpa:52;
263 };
264};
265
266/* Definitions for the monitored notification facility */
267union hv_monitor_trigger_group {
268 u64 as_uint64;
269 struct {
270 u32 pending;
271 u32 armed;
272 };
273};
274
275struct hv_monitor_parameter {
276 union hv_connection_id connectionid;
277 u16 flagnumber;
278 u16 rsvdz;
279};
280
281union hv_monitor_trigger_state {
282 u32 asu32;
283
284 struct {
285 u32 group_enable:4;
286 u32 rsvdz:28;
287 };
288};
289
290/* struct hv_monitor_page Layout */
291/* ------------------------------------------------------ */
292/* | 0 | TriggerState (4 bytes) | Rsvd1 (4 bytes) | */
293/* | 8 | TriggerGroup[0] | */
294/* | 10 | TriggerGroup[1] | */
295/* | 18 | TriggerGroup[2] | */
296/* | 20 | TriggerGroup[3] | */
297/* | 28 | Rsvd2[0] | */
298/* | 30 | Rsvd2[1] | */
299/* | 38 | Rsvd2[2] | */
300/* | 40 | NextCheckTime[0][0] | NextCheckTime[0][1] | */
301/* | ... | */
302/* | 240 | Latency[0][0..3] | */
303/* | 340 | Rsvz3[0] | */
304/* | 440 | Parameter[0][0] | */
305/* | 448 | Parameter[0][1] | */
306/* | ... | */
307/* | 840 | Rsvd4[0] | */
308/* ------------------------------------------------------ */
309struct hv_monitor_page {
310 union hv_monitor_trigger_state trigger_state;
311 u32 rsvdz1;
312
313 union hv_monitor_trigger_group trigger_group[4];
314 u64 rsvdz2[3];
315
316 s32 next_checktime[4][32];
317
318 u16 latency[4][32];
319 u64 rsvdz3[32];
320
321 struct hv_monitor_parameter parameter[4][32];
322
323 u8 rsvdz4[1984];
324};
325
326/* Declare the various hypercall operations. */
327enum hv_call_code {
328 HVCALL_POST_MESSAGE = 0x005c,
329 HVCALL_SIGNAL_EVENT = 0x005d,
330};
331
332/* Definition of the hv_post_message hypercall input structure. */
333struct hv_input_post_message {
334 union hv_connection_id connectionid;
335 u32 reserved;
336 enum hv_message_type message_type;
337 u32 payload_size;
338 u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
339};
340
341/* Definition of the hv_signal_event hypercall input structure. */
342struct hv_input_signal_event {
343 union hv_connection_id connectionid;
344 u16 flag_number;
345 u16 rsvdz;
346};
347
348/*
349 * Versioning definitions used for guests reporting themselves to the
350 * hypervisor, and visa versa.
351 */
352
353/* Version info reported by guest OS's */
354enum hv_guest_os_vendor {
355 HVGUESTOS_VENDOR_MICROSOFT = 0x0001
356};
357
358enum hv_guest_os_microsoft_ids {
359 HVGUESTOS_MICROSOFT_UNDEFINED = 0x00,
360 HVGUESTOS_MICROSOFT_MSDOS = 0x01,
361 HVGUESTOS_MICROSOFT_WINDOWS3X = 0x02,
362 HVGUESTOS_MICROSOFT_WINDOWS9X = 0x03,
363 HVGUESTOS_MICROSOFT_WINDOWSNT = 0x04,
364 HVGUESTOS_MICROSOFT_WINDOWSCE = 0x05
365};
366
367/*
368 * Declare the MSR used to identify the guest OS.
369 */
370#define HV_X64_MSR_GUEST_OS_ID 0x40000000
371
372union hv_x64_msr_guest_os_id_contents {
373 u64 as_uint64;
374 struct {
375 u64 build_number:16;
376 u64 service_version:8; /* Service Pack, etc. */
377 u64 minor_version:8;
378 u64 major_version:8;
379 u64 os_id:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */
380 u64 vendor_id:16; /* enum hv_guest_os_vendor */
381 };
382};
383
384/*
385 * Declare the MSR used to setup pages used to communicate with the hypervisor.
386 */
387#define HV_X64_MSR_HYPERCALL 0x40000001
388
389union hv_x64_msr_hypercall_contents {
390 u64 as_uint64;
391 struct {
392 u64 enable:1;
393 u64 reserved:11;
394 u64 guest_physical_address:52;
395 };
396};
397
398
399enum {
400 VMBUS_MESSAGE_CONNECTION_ID = 1,
401 VMBUS_MESSAGE_PORT_ID = 1,
402 VMBUS_EVENT_CONNECTION_ID = 2,
403 VMBUS_EVENT_PORT_ID = 2,
404 VMBUS_MONITOR_CONNECTION_ID = 3,
405 VMBUS_MONITOR_PORT_ID = 3,
406 VMBUS_MESSAGE_SINT = 2,
407};
408
409/* #defines */
410
411#define HV_PRESENT_BIT 0x80000000
412
413#define HV_LINUX_GUEST_ID_LO 0x00000000
414#define HV_LINUX_GUEST_ID_HI 0xB16B00B5
415#define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \
416 HV_LINUX_GUEST_ID_LO)
417
418#define HV_CPU_POWER_MANAGEMENT (1 << 0)
419#define HV_RECOMMENDATIONS_MAX 4
420
421#define HV_X64_MAX 5
422#define HV_CAPS_MAX 8
423
424
425#define HV_HYPERCALL_PARAM_ALIGN sizeof(u64)
426
427
428/* Service definitions */
429
430#define HV_SERVICE_PARENT_PORT (0)
431#define HV_SERVICE_PARENT_CONNECTION (0)
432
433#define HV_SERVICE_CONNECT_RESPONSE_SUCCESS (0)
434#define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER (1)
435#define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE (2)
436#define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED (3)
437
438#define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID (1)
439#define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID (2)
440#define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID (3)
441#define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID (4)
442#define HV_SERVICE_MAX_MESSAGE_ID (4)
443
444#define HV_SERVICE_PROTOCOL_VERSION (0x0010)
445#define HV_CONNECT_PAYLOAD_BYTE_COUNT 64
446
447/* #define VMBUS_REVISION_NUMBER 6 */
448
449/* Our local vmbus's port and connection id. Anything >0 is fine */
450/* #define VMBUS_PORT_ID 11 */
451
452/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
453static const uuid_le VMBUS_SERVICE_ID = {
454 .b = {
455 0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
456 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
457 },
458};
459
460#define MAX_NUM_CPUS 32
461
462
463struct hv_input_signal_event_buffer {
464 u64 align8;
465 struct hv_input_signal_event event;
466};
467
468struct hv_context {
469 /* We only support running on top of Hyper-V
470 * So at this point this really can only contain the Hyper-V ID
471 */
472 u64 guestid;
473
474 void *hypercall_page;
475
476 bool synic_initialized;
477
478 /*
479 * This is used as an input param to HvCallSignalEvent hypercall. The
480 * input param is immutable in our usage and must be dynamic mem (vs
481 * stack or global). */
482 struct hv_input_signal_event_buffer *signal_event_buffer;
483 /* 8-bytes aligned of the buffer above */
484 struct hv_input_signal_event *signal_event_param;
485
486 void *synic_message_page[MAX_NUM_CPUS];
487 void *synic_event_page[MAX_NUM_CPUS];
488};
489
490extern struct hv_context hv_context;
491
492
493/* Hv Interface */
494
495extern int hv_init(void);
496
497extern void hv_cleanup(void);
498
499extern u16 hv_post_message(union hv_connection_id connection_id,
500 enum hv_message_type message_type,
501 void *payload, size_t payload_size);
502
503extern u16 hv_signal_event(void);
504
505extern void hv_synic_init(void *irqarg);
506
507extern void hv_synic_cleanup(void *arg);
508
509
510/* Interface */
511
512
513int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer,
514 u32 buflen);
515
516void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
517
518int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
519 struct scatterlist *sglist,
520 u32 sgcount);
521
522int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
523 u32 buflen);
524
525int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
526 void *buffer,
527 u32 buflen,
528 u32 offset);
529
530u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info);
531
532void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix);
533
534void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
535 struct hv_ring_buffer_debug_info *debug_info);
536
537/*
538 * Maximum channels is determined by the size of the interrupt page
539 * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
540 * and the other is receive endpoint interrupt
541 */
542#define MAX_NUM_CHANNELS ((PAGE_SIZE >> 1) << 3) /* 16348 channels */
543
544/* The value here must be in multiple of 32 */
545/* TODO: Need to make this configurable */
546#define MAX_NUM_CHANNELS_SUPPORTED 256
547
548
549enum vmbus_connect_state {
550 DISCONNECTED,
551 CONNECTING,
552 CONNECTED,
553 DISCONNECTING
554};
555
556#define MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT
557
558struct vmbus_connection {
559 enum vmbus_connect_state conn_state;
560
561 atomic_t next_gpadl_handle;
562
563 /*
564 * Represents channel interrupts. Each bit position represents a
565 * channel. When a channel sends an interrupt via VMBUS, it finds its
566 * bit in the sendInterruptPage, set it and calls Hv to generate a port
567 * event. The other end receives the port event and parse the
568 * recvInterruptPage to see which bit is set
569 */
570 void *int_page;
571 void *send_int_page;
572 void *recv_int_page;
573
574 /*
575 * 2 pages - 1st page for parent->child notification and 2nd
576 * is child->parent notification
577 */
578 void *monitor_pages;
579 struct list_head chn_msg_list;
580 spinlock_t channelmsg_lock;
581
582 /* List of channels */
583 struct list_head chn_list;
584 spinlock_t channel_lock;
585
586 struct workqueue_struct *work_queue;
587};
588
589
590struct vmbus_msginfo {
591 /* Bookkeeping stuff */
592 struct list_head msglist_entry;
593
594 /* The message itself */
595 unsigned char msg[0];
596};
597
598
599extern struct vmbus_connection vmbus_connection;
600
601/* General vmbus interface */
602
603struct hv_device *vmbus_device_create(uuid_le *type,
604 uuid_le *instance,
605 struct vmbus_channel *channel);
606
607int vmbus_device_register(struct hv_device *child_device_obj);
608void vmbus_device_unregister(struct hv_device *device_obj);
609
610/* static void */
611/* VmbusChildDeviceDestroy( */
612/* struct hv_device *); */
613
614struct vmbus_channel *relid2channel(u32 relid);
615
616
617/* Connection interface */
618
619int vmbus_connect(void);
620
621int vmbus_post_msg(void *buffer, size_t buflen);
622
623int vmbus_set_event(u32 child_relid);
624
625void vmbus_on_event(unsigned long data);
626
627
628#endif /* _HYPERV_VMBUS_H */