iPXE
vmbus.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * Hyper-V virtual machine bus
29 *
30 */
31
32#include <stdint.h>
33#include <stdlib.h>
34#include <stdio.h>
35#include <string.h>
36#include <errno.h>
37#include <assert.h>
38#include <byteswap.h>
39#include <ipxe/nap.h>
40#include <ipxe/malloc.h>
41#include <ipxe/iobuf.h>
42#include <ipxe/bitops.h>
43#include <ipxe/hyperv.h>
44#include <ipxe/vmbus.h>
45
46/** VMBus initial GPADL ID
47 *
48 * This is an opaque value with no meaning. The Linux kernel uses
49 * 0xe1e10.
50 */
51#define VMBUS_GPADL_MAGIC 0x18ae0000
52
53/** Current (i.e. most recently issued) GPADL ID */
54static unsigned int vmbus_gpadl = VMBUS_GPADL_MAGIC;
55
56/** Obsolete GPADL ID threshold
57 *
58 * When the Hyper-V connection is reset, any previous GPADLs are
59 * automatically rendered obsolete.
60 */
62
63/**
64 * Post message
65 *
66 * @v hv Hyper-V hypervisor
67 * @v header Message header
68 * @v len Length of message (including header)
69 * @ret rc Return status code
70 */
71static int vmbus_post_message ( struct hv_hypervisor *hv,
72 const struct vmbus_message_header *header,
73 size_t len ) {
74 struct vmbus *vmbus = hv->vmbus;
75 int rc;
76
77 /* Post message */
79 header, len ) ) != 0 ) {
80 DBGC ( vmbus, "VMBUS %p could not post message: %s\n",
81 vmbus, strerror ( rc ) );
82 return rc;
83 }
84
85 return 0;
86}
87
88/**
89 * Post empty message
90 *
91 * @v hv Hyper-V hypervisor
92 * @v type Message type
93 * @ret rc Return status code
94 */
96 unsigned int type ) {
97 struct vmbus_message_header header = { .type = cpu_to_le32 ( type ) };
98
99 return vmbus_post_message ( hv, &header, sizeof ( header ) );
100}
101
102/**
103 * Wait for received message of any type
104 *
105 * @v hv Hyper-V hypervisor
106 * @ret rc Return status code
107 */
108static int vmbus_wait_for_any_message ( struct hv_hypervisor *hv ) {
109 struct vmbus *vmbus = hv->vmbus;
110 int rc;
111
112 /* Wait for message */
113 if ( ( rc = hv_wait_for_message ( hv, VMBUS_MESSAGE_SINT ) ) != 0 ) {
114 DBGC ( vmbus, "VMBUS %p failed waiting for message: %s\n",
115 vmbus, strerror ( rc ) );
116 return rc;
117 }
118
119 /* Sanity check */
121 DBGC ( vmbus, "VMBUS %p invalid message type %d\n",
123 return -EINVAL;
124 }
125
126 return 0;
127}
128
129/**
130 * Wait for received message of a specified type, ignoring any others
131 *
132 * @v hv Hyper-V hypervisor
133 * @v type Message type
134 * @ret rc Return status code
135 */
136static int vmbus_wait_for_message ( struct hv_hypervisor *hv,
137 unsigned int type ) {
138 struct vmbus *vmbus = hv->vmbus;
140 int rc;
141
142 /* Loop until specified message arrives, or until an error occurs */
143 while ( 1 ) {
144
145 /* Wait for message */
146 if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
147 return rc;
148
149 /* Check for requested message type */
150 if ( header->type == cpu_to_le32 ( type ) )
151 return 0;
152
153 /* Ignore any other messages (e.g. due to additional
154 * channels being offered at runtime).
155 */
156 DBGC ( vmbus, "VMBUS %p ignoring message type %d (expecting "
157 "%d)\n", vmbus, le32_to_cpu ( header->type ), type );
158 }
159}
160
161/**
162 * Initiate contact
163 *
164 * @v hv Hyper-V hypervisor
165 * @v raw VMBus protocol (raw) version
166 * @ret rc Return status code
167 */
168static int vmbus_initiate_contact ( struct hv_hypervisor *hv,
169 unsigned int raw ) {
170 struct vmbus *vmbus = hv->vmbus;
172 struct vmbus_initiate_contact initiate;
173 int rc;
174
175 /* Construct message */
176 memset ( &initiate, 0, sizeof ( initiate ) );
178 initiate.version.raw = cpu_to_le32 ( raw );
179 initiate.intr = virt_to_phys ( vmbus->intr );
180 initiate.monitor_in = virt_to_phys ( vmbus->monitor_in );
181 initiate.monitor_out = virt_to_phys ( vmbus->monitor_out );
182
183 /* Post message */
184 if ( ( rc = vmbus_post_message ( hv, &initiate.header,
185 sizeof ( initiate ) ) ) != 0 )
186 return rc;
187
188 /* Wait for response */
189 if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_VERSION_RESPONSE ) ) !=0)
190 return rc;
191
192 /* Check response */
193 if ( ! version->supported ) {
194 DBGC ( vmbus, "VMBUS %p requested version not supported\n",
195 vmbus );
196 return -ENOTSUP;
197 }
198
199 DBGC ( vmbus, "VMBUS %p initiated contact using version %d.%d\n",
200 vmbus, le16_to_cpu ( initiate.version.major ),
201 le16_to_cpu ( initiate.version.minor ) );
202 return 0;
203}
204
205/**
206 * Terminate contact
207 *
208 * @v hv Hyper-V hypervisor
209 * @ret rc Return status code
210 */
211static int vmbus_unload ( struct hv_hypervisor *hv ) {
212 int rc;
213
214 /* Post message */
215 if ( ( rc = vmbus_post_empty_message ( hv, VMBUS_UNLOAD ) ) != 0 )
216 return rc;
217
218 /* Wait for response */
219 if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_UNLOAD_RESPONSE ) ) != 0)
220 return rc;
221
222 return 0;
223}
224
225/**
226 * Negotiate protocol version
227 *
228 * @v hv Hyper-V hypervisor
229 * @ret rc Return status code
230 */
231static int vmbus_negotiate_version ( struct hv_hypervisor *hv ) {
232 int rc;
233
234 /* We require the ability to disconnect from and reconnect to
235 * VMBus; if we don't have this then there is no (viable) way
236 * for a loaded operating system to continue to use any VMBus
237 * devices. (There is also a small but non-zero risk that the
238 * host will continue to write to our interrupt and monitor
239 * pages, since the VMBUS_UNLOAD message in earlier versions
240 * is essentially a no-op.)
241 *
242 * This requires us to ensure that the host supports protocol
243 * version 3.0 (VMBUS_VERSION_WIN8_1). However, we can't
244 * actually _use_ protocol version 3.0, since doing so causes
245 * an iSCSI-booted Windows Server 2012 R2 VM to crash due to a
246 * NULL pointer dereference in vmbus.sys.
247 *
248 * To work around this problem, we first ensure that we can
249 * connect using protocol v3.0, then disconnect and reconnect
250 * using the oldest known protocol.
251 */
252
253 /* Initiate contact to check for required protocol support */
254 if ( ( rc = vmbus_initiate_contact ( hv, VMBUS_VERSION_WIN8_1 ) ) != 0 )
255 return rc;
256
257 /* Terminate contact */
258 if ( ( rc = vmbus_unload ( hv ) ) != 0 )
259 return rc;
260
261 /* Reinitiate contact using the oldest known protocol version */
262 if ( ( rc = vmbus_initiate_contact ( hv, VMBUS_VERSION_WS2008 ) ) != 0 )
263 return rc;
264
265 return 0;
266}
267
268/**
269 * Establish GPA descriptor list
270 *
271 * @v vmdev VMBus device
272 * @v data Data buffer
273 * @v len Length of data buffer
274 * @ret gpadl GPADL ID, or negative error
275 */
276int vmbus_establish_gpadl ( struct vmbus_device *vmdev, void *data,
277 size_t len ) {
278 struct hv_hypervisor *hv = vmdev->hv;
279 struct vmbus *vmbus = hv->vmbus;
280 physaddr_t addr = virt_to_phys ( data );
281 unsigned int pfn_count = hv_pfn_count ( addr, len );
282 struct {
283 struct vmbus_gpadl_header gpadlhdr;
284 struct vmbus_gpa_range range;
285 uint64_t pfn[pfn_count];
286 } __attribute__ (( packed )) gpadlhdr;
287 const struct vmbus_gpadl_created *created = &vmbus->message->created;
288 unsigned int gpadl;
289 unsigned int i;
290 int rc;
291
292 /* Allocate GPADL ID */
293 gpadl = ++vmbus_gpadl;
294
295 /* Construct message */
296 memset ( &gpadlhdr, 0, sizeof ( gpadlhdr ) );
297 gpadlhdr.gpadlhdr.header.type = cpu_to_le32 ( VMBUS_GPADL_HEADER );
298 gpadlhdr.gpadlhdr.channel = cpu_to_le32 ( vmdev->channel );
299 gpadlhdr.gpadlhdr.gpadl = cpu_to_le32 ( gpadl );
300 gpadlhdr.gpadlhdr.range_len =
301 cpu_to_le16 ( ( sizeof ( gpadlhdr.range ) +
302 sizeof ( gpadlhdr.pfn ) ) );
303 gpadlhdr.gpadlhdr.range_count = cpu_to_le16 ( 1 );
304 gpadlhdr.range.len = cpu_to_le32 ( len );
305 gpadlhdr.range.offset = cpu_to_le32 ( addr & ( PAGE_SIZE - 1 ) );
306 for ( i = 0 ; i < pfn_count ; i++ )
307 gpadlhdr.pfn[i] = ( ( addr / PAGE_SIZE ) + i );
308
309 /* Post message */
310 if ( ( rc = vmbus_post_message ( hv, &gpadlhdr.gpadlhdr.header,
311 sizeof ( gpadlhdr ) ) ) != 0 )
312 return rc;
313
314 /* Wait for response */
315 if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_GPADL_CREATED ) ) != 0 )
316 return rc;
317
318 /* Check response */
319 if ( created->channel != cpu_to_le32 ( vmdev->channel ) ) {
320 DBGC ( vmdev, "VMBUS %s unexpected GPADL channel %d\n",
321 vmdev->dev.name, le32_to_cpu ( created->channel ) );
322 return -EPROTO;
323 }
324 if ( created->gpadl != cpu_to_le32 ( gpadl ) ) {
325 DBGC ( vmdev, "VMBUS %s unexpected GPADL ID %#08x\n",
326 vmdev->dev.name, le32_to_cpu ( created->gpadl ) );
327 return -EPROTO;
328 }
329 if ( created->status != 0 ) {
330 DBGC ( vmdev, "VMBUS %s GPADL creation failed: %#08x\n",
331 vmdev->dev.name, le32_to_cpu ( created->status ) );
332 return -EPROTO;
333 }
334
335 DBGC ( vmdev, "VMBUS %s GPADL %#08x is [%08lx,%08lx)\n",
336 vmdev->dev.name, gpadl, addr, ( addr + len ) );
337 return gpadl;
338}
339
340/**
341 * Tear down GPA descriptor list
342 *
343 * @v vmdev VMBus device
344 * @v gpadl GPADL ID
345 * @ret rc Return status code
346 */
347int vmbus_gpadl_teardown ( struct vmbus_device *vmdev, unsigned int gpadl ) {
348 struct hv_hypervisor *hv = vmdev->hv;
349 struct vmbus *vmbus = hv->vmbus;
350 struct vmbus_gpadl_teardown teardown;
351 const struct vmbus_gpadl_torndown *torndown = &vmbus->message->torndown;
352 int rc;
353
354 /* If GPADL is obsolete (i.e. was created before the most
355 * recent Hyper-V reset), then we will never receive a
356 * response to the teardown message. Since the GPADL is
357 * already destroyed as far as the hypervisor is concerned, no
358 * further action is required.
359 */
361 return 0;
362
363 /* Construct message */
364 memset ( &teardown, 0, sizeof ( teardown ) );
366 teardown.channel = cpu_to_le32 ( vmdev->channel );
367 teardown.gpadl = cpu_to_le32 ( gpadl );
368
369 /* Post message */
370 if ( ( rc = vmbus_post_message ( hv, &teardown.header,
371 sizeof ( teardown ) ) ) != 0 )
372 return rc;
373
374 /* Wait for response */
375 if ( ( rc = vmbus_wait_for_message ( hv, VMBUS_GPADL_TORNDOWN ) ) != 0 )
376 return rc;
377
378 /* Check response */
379 if ( torndown->gpadl != cpu_to_le32 ( gpadl ) ) {
380 DBGC ( vmdev, "VMBUS %s unexpected GPADL ID %#08x\n",
381 vmdev->dev.name, le32_to_cpu ( torndown->gpadl ) );
382 return -EPROTO;
383 }
384
385 return 0;
386}
387
388/**
389 * Open VMBus channel
390 *
391 * @v vmdev VMBus device
392 * @v op Channel operations
393 * @v out_len Outbound ring buffer length
394 * @v in_len Inbound ring buffer length
395 * @v mtu Maximum expected data packet length (including headers)
396 * @ret rc Return status code
397 *
398 * Both outbound and inbound ring buffer lengths must be a power of
399 * two and a multiple of PAGE_SIZE. The requirement to be a power of
400 * two is a policy decision taken to simplify the ring buffer indexing
401 * logic.
402 */
403int vmbus_open ( struct vmbus_device *vmdev,
405 size_t out_len, size_t in_len, size_t mtu ) {
406 struct hv_hypervisor *hv = vmdev->hv;
407 struct vmbus *vmbus = hv->vmbus;
409 const struct vmbus_open_channel_result *opened =
411 size_t len;
412 void *ring;
413 void *packet;
414 int gpadl;
415 uint32_t open_id;
416 int rc;
417
418 /* Sanity checks */
419 assert ( ( out_len % PAGE_SIZE ) == 0 );
420 assert ( ( out_len & ( out_len - 1 ) ) == 0 );
421 assert ( ( in_len % PAGE_SIZE ) == 0 );
422 assert ( ( in_len & ( in_len - 1 ) ) == 0 );
423 assert ( mtu >= ( sizeof ( struct vmbus_packet_header ) +
424 sizeof ( struct vmbus_packet_footer ) ) );
425
426 /* Allocate packet buffer */
427 packet = malloc ( mtu );
428 if ( ! packet ) {
429 rc = -ENOMEM;
430 goto err_alloc_packet;
431 }
432
433 /* Allocate ring buffer */
434 len = ( sizeof ( *vmdev->out ) + out_len +
435 sizeof ( *vmdev->in ) + in_len );
436 assert ( ( len % PAGE_SIZE ) == 0 );
437 ring = malloc_phys ( len, PAGE_SIZE );
438 if ( ! ring ) {
439 rc = -ENOMEM;
440 goto err_alloc_ring;
441 }
442 memset ( ring, 0, len );
443
444 /* Establish GPADL for ring buffer */
445 gpadl = vmbus_establish_gpadl ( vmdev, ring, len );
446 if ( gpadl < 0 ) {
447 rc = gpadl;
448 goto err_establish;
449 }
450
451 /* Construct message */
452 memset ( &open, 0, sizeof ( open ) );
453 open.header.type = cpu_to_le32 ( VMBUS_OPEN_CHANNEL );
454 open.channel = cpu_to_le32 ( vmdev->channel );
455 open_id = random();
456 open.id = open_id; /* Opaque random value: endianness irrelevant */
457 open.gpadl = cpu_to_le32 ( gpadl );
458 open.out_pages = ( ( sizeof ( *vmdev->out ) / PAGE_SIZE ) +
459 ( out_len / PAGE_SIZE ) );
460
461 /* Post message */
462 if ( ( rc = vmbus_post_message ( hv, &open.header,
463 sizeof ( open ) ) ) != 0 )
464 goto err_post_message;
465
466 /* Wait for response */
467 if ( ( rc = vmbus_wait_for_message ( hv,
469 goto err_wait_for_message;
470
471 /* Check response */
472 if ( opened->channel != cpu_to_le32 ( vmdev->channel ) ) {
473 DBGC ( vmdev, "VMBUS %s unexpected opened channel %#08x\n",
474 vmdev->dev.name, le32_to_cpu ( opened->channel ) );
475 rc = -EPROTO;
476 goto err_check_response;
477 }
478 if ( opened->id != open_id /* Non-endian */ ) {
479 DBGC ( vmdev, "VMBUS %s unexpected open ID %#08x\n",
480 vmdev->dev.name, le32_to_cpu ( opened->id ) );
481 rc = -EPROTO;
482 goto err_check_response;
483 }
484 if ( opened->status != 0 ) {
485 DBGC ( vmdev, "VMBUS %s open failed: %#08x\n",
486 vmdev->dev.name, le32_to_cpu ( opened->status ) );
487 rc = -EPROTO;
488 goto err_check_response;
489 }
490
491 /* Store channel parameters */
492 vmdev->out_len = out_len;
493 vmdev->in_len = in_len;
494 vmdev->out = ring;
495 vmdev->in = ( ring + sizeof ( *vmdev->out ) + out_len );
496 vmdev->gpadl = gpadl;
497 vmdev->op = op;
498 vmdev->mtu = mtu;
499 vmdev->packet = packet;
500
501 DBGC ( vmdev, "VMBUS %s channel GPADL %#08x ring "
502 "[%#08lx,%#08lx,%#08lx)\n", vmdev->dev.name, vmdev->gpadl,
503 virt_to_phys ( vmdev->out ), virt_to_phys ( vmdev->in ),
504 ( virt_to_phys ( vmdev->out ) + len ) );
505 return 0;
506
507 err_check_response:
508 err_wait_for_message:
509 err_post_message:
510 vmbus_gpadl_teardown ( vmdev, vmdev->gpadl );
511 err_establish:
512 free_phys ( ring, len );
513 err_alloc_ring:
514 free ( packet );
515 err_alloc_packet:
516 return rc;
517}
518
519/**
520 * Close VMBus channel
521 *
522 * @v vmdev VMBus device
523 */
524void vmbus_close ( struct vmbus_device *vmdev ) {
525 struct hv_hypervisor *hv = vmdev->hv;
527 size_t len;
528 int rc;
529
530 /* Construct message */
531 memset ( &close, 0, sizeof ( close ) );
532 close.header.type = cpu_to_le32 ( VMBUS_CLOSE_CHANNEL );
533 close.channel = cpu_to_le32 ( vmdev->channel );
534
535 /* Post message */
536 if ( ( rc = vmbus_post_message ( hv, &close.header,
537 sizeof ( close ) ) ) != 0 ) {
538 DBGC ( vmdev, "VMBUS %s failed to close: %s\n",
539 vmdev->dev.name, strerror ( rc ) );
540 /* Continue to attempt to tear down GPADL, so that our
541 * memory is no longer accessible by the remote VM.
542 */
543 }
544
545 /* Tear down GPADL */
546 if ( ( rc = vmbus_gpadl_teardown ( vmdev, vmdev->gpadl ) ) != 0 ) {
547 DBGC ( vmdev, "VMBUS %s failed to tear down channel GPADL: "
548 "%s\n", vmdev->dev.name, strerror ( rc ) );
549 /* We can't prevent the remote VM from continuing to
550 * access this memory, so leak it.
551 */
552 return;
553 }
554
555 /* Free ring buffer */
556 len = ( sizeof ( *vmdev->out ) + vmdev->out_len +
557 sizeof ( *vmdev->in ) + vmdev->in_len );
558 free_phys ( vmdev->out, len );
559 vmdev->out = NULL;
560 vmdev->in = NULL;
561
562 /* Free packet buffer */
563 free ( vmdev->packet );
564 vmdev->packet = NULL;
565
566 DBGC ( vmdev, "VMBUS %s closed\n", vmdev->dev.name );
567}
568
569/**
570 * Signal channel via monitor page
571 *
572 * @v vmdev VMBus device
573 */
574static void vmbus_signal_monitor ( struct vmbus_device *vmdev ) {
575 struct hv_hypervisor *hv = vmdev->hv;
576 struct vmbus *vmbus = hv->vmbus;
578 unsigned int group;
579 unsigned int bit;
580
581 /* Set bit in monitor trigger group */
582 group = ( vmdev->monitor / ( 8 * sizeof ( trigger->pending ) ));
583 bit = ( vmdev->monitor % ( 8 * sizeof ( trigger->pending ) ) );
585 set_bit ( bit, trigger );
586}
587
588/**
589 * Signal channel via hypervisor event
590 *
591 * @v vmdev VMBus device
592 */
593static void vmbus_signal_event ( struct vmbus_device *vmdev ) {
594 struct hv_hypervisor *hv = vmdev->hv;
595 int rc;
596
597 /* Signal hypervisor event */
598 if ( ( rc = hv_signal_event ( hv, VMBUS_EVENT_ID, 0 ) ) != 0 ) {
599 DBGC ( vmdev, "VMBUS %s could not signal event: %s\n",
600 vmdev->dev.name, strerror ( rc ) );
601 return;
602 }
603}
604
605/**
606 * Fill outbound ring buffer
607 *
608 * @v vmdev VMBus device
609 * @v prod Producer index
610 * @v data Data
611 * @v len Length
612 * @ret prod New producer index
613 *
614 * The caller must ensure that there is sufficient space in the ring
615 * buffer.
616 */
617static size_t vmbus_produce ( struct vmbus_device *vmdev, size_t prod,
618 const void *data, size_t len ) {
619 size_t first;
620 size_t second;
621
622 /* Determine fragment lengths */
623 first = ( vmdev->out_len - prod );
624 if ( first > len )
625 first = len;
626 second = ( len - first );
627
628 /* Copy fragment(s) */
629 memcpy ( &vmdev->out->data[prod], data, first );
630 if ( second )
631 memcpy ( &vmdev->out->data[0], ( data + first ), second );
632
633 return ( ( prod + len ) & ( vmdev->out_len - 1 ) );
634}
635
636/**
637 * Consume inbound ring buffer
638 *
639 * @v vmdev VMBus device
640 * @v cons Consumer index
641 * @v data Data buffer, or NULL
642 * @v len Length to consume
643 * @ret cons New consumer index
644 */
645static size_t vmbus_consume ( struct vmbus_device *vmdev, size_t cons,
646 void *data, size_t len ) {
647 size_t first;
648 size_t second;
649
650 /* Determine fragment lengths */
651 first = ( vmdev->in_len - cons );
652 if ( first > len )
653 first = len;
654 second = ( len - first );
655
656 /* Copy fragment(s) */
657 memcpy ( data, &vmdev->in->data[cons], first );
658 if ( second )
659 memcpy ( ( data + first ), &vmdev->in->data[0], second );
660
661 return ( ( cons + len ) & ( vmdev->in_len - 1 ) );
662}
663
664/**
665 * Send packet via ring buffer
666 *
667 * @v vmdev VMBus device
668 * @v header Packet header
669 * @v data Data
670 * @v len Length of data
671 * @ret rc Return status code
672 *
673 * Send a packet via the outbound ring buffer. All fields in the
674 * packet header must be filled in, with the exception of the total
675 * packet length.
676 */
677static int vmbus_send ( struct vmbus_device *vmdev,
679 const void *data, size_t len ) {
680 struct hv_hypervisor *hv = vmdev->hv;
681 struct vmbus *vmbus = hv->vmbus;
682 static uint8_t padding[ 8 - 1 ];
683 struct vmbus_packet_footer footer;
684 size_t header_len;
685 size_t pad_len;
686 size_t footer_len;
687 size_t ring_len;
688 size_t cons;
689 size_t prod;
690 size_t old_prod;
691 size_t fill;
692
693 /* Sanity check */
694 assert ( vmdev->out != NULL );
695
696 /* Calculate lengths */
697 header_len = ( le16_to_cpu ( header->hdr_qlen ) * 8 );
698 pad_len = ( ( -len ) & ( 8 - 1 ) );
699 footer_len = sizeof ( footer );
700 ring_len = ( header_len + len + pad_len + footer_len );
701
702 /* Check that we have enough room in the outbound ring buffer */
703 cons = le32_to_cpu ( vmdev->out->cons );
704 prod = le32_to_cpu ( vmdev->out->prod );
705 old_prod = prod;
706 fill = ( ( prod - cons ) & ( vmdev->out_len - 1 ) );
707 if ( ( fill + ring_len ) >= vmdev->out_len ) {
708 DBGC ( vmdev, "VMBUS %s ring buffer full\n", vmdev->dev.name );
709 return -ENOBUFS;
710 }
711
712 /* Complete header */
713 header->qlen = cpu_to_le16 ( ( ring_len - footer_len ) / 8 );
714
715 /* Construct footer */
716 footer.reserved = 0;
717 footer.prod = vmdev->out->prod;
718
719 /* Copy packet to buffer */
720 DBGC2 ( vmdev, "VMBUS %s sending:\n", vmdev->dev.name );
721 DBGC2_HDA ( vmdev, prod, header, header_len );
722 prod = vmbus_produce ( vmdev, prod, header, header_len );
723 DBGC2_HDA ( vmdev, prod, data, len );
724 prod = vmbus_produce ( vmdev, prod, data, len );
725 prod = vmbus_produce ( vmdev, prod, padding, pad_len );
726 DBGC2_HDA ( vmdev, prod, &footer, sizeof ( footer ) );
727 prod = vmbus_produce ( vmdev, prod, &footer, sizeof ( footer ) );
728 assert ( ( ( prod - old_prod ) & ( vmdev->out_len - 1 ) ) == ring_len );
729
730 /* Update producer index */
731 wmb();
732 vmdev->out->prod = cpu_to_le32 ( prod );
733
734 /* Return if we do not need to signal the host. This follows
735 * the logic of hv_need_to_signal() in the Linux driver.
736 */
737 mb();
738 if ( vmdev->out->intr_mask )
739 return 0;
740 rmb();
741 cons = le32_to_cpu ( vmdev->out->cons );
742 if ( cons != old_prod )
743 return 0;
744
745 /* Set channel bit in interrupt page */
746 set_bit ( vmdev->channel, vmbus->intr->out );
747
748 /* Signal the host */
749 vmdev->signal ( vmdev );
750
751 return 0;
752}
753
754/**
755 * Send control packet via ring buffer
756 *
757 * @v vmdev VMBus device
758 * @v xid Transaction ID (or zero to not request completion)
759 * @v data Data
760 * @v len Length of data
761 * @ret rc Return status code
762 *
763 * Send data using a VMBUS_DATA_INBAND packet.
764 */
765int vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid,
766 const void *data, size_t len ) {
767 struct vmbus_packet_header *header = vmdev->packet;
768
769 /* Construct header in packet buffer */
770 assert ( header != NULL );
772 header->hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 );
773 header->flags = ( xid ?
775 header->xid = xid; /* Non-endian */
776
777 return vmbus_send ( vmdev, header, data, len );
778}
779
780/**
781 * Send data packet via ring buffer
782 *
783 * @v vmdev VMBus device
784 * @v xid Transaction ID
785 * @v data Data
786 * @v len Length of data
787 * @v iobuf I/O buffer
788 * @ret rc Return status code
789 *
790 * Send data using a VMBUS_DATA_GPA_DIRECT packet. The caller is
791 * responsible for ensuring that the I/O buffer remains untouched
792 * until the corresponding completion has been received.
793 */
795 const void *data, size_t len, struct io_buffer *iobuf ) {
796 physaddr_t addr = virt_to_phys ( iobuf->data );
797 unsigned int pfn_count = hv_pfn_count ( addr, iob_len ( iobuf ) );
798 struct {
799 struct vmbus_gpa_direct_header gpa;
800 struct vmbus_gpa_range range;
801 uint64_t pfn[pfn_count];
802 } __attribute__ (( packed )) *header = vmdev->packet;
803 unsigned int i;
804
805 /* Sanity check */
806 assert ( header != NULL );
807 assert ( sizeof ( *header ) <= vmdev->mtu );
808
809 /* Construct header in packet buffer */
810 header->gpa.header.type = cpu_to_le16 ( VMBUS_DATA_GPA_DIRECT );
811 header->gpa.header.hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 );
812 header->gpa.header.flags = cpu_to_le16 ( VMBUS_COMPLETION_REQUESTED );
813 header->gpa.header.xid = xid; /* Non-endian */
814 header->gpa.range_count = 1;
815 header->range.len = cpu_to_le32 ( iob_len ( iobuf ) );
816 header->range.offset = cpu_to_le32 ( addr & ( PAGE_SIZE - 1 ) );
817 for ( i = 0 ; i < pfn_count ; i++ )
818 header->pfn[i] = ( ( addr / PAGE_SIZE ) + i );
819
820 return vmbus_send ( vmdev, &header->gpa.header, data, len );
821}
822
823/**
824 * Send completion packet via ring buffer
825 *
826 * @v vmdev VMBus device
827 * @v xid Transaction ID
828 * @v data Data
829 * @v len Length of data
830 * @ret rc Return status code
831 *
832 * Send data using a VMBUS_COMPLETION packet.
833 */
835 const void *data, size_t len ) {
836 struct vmbus_packet_header *header = vmdev->packet;
837
838 /* Construct header in packet buffer */
839 assert ( header != NULL );
841 header->hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 );
842 header->flags = 0;
843 header->xid = xid; /* Non-endian */
844
845 return vmbus_send ( vmdev, header, data, len );
846}
847
848/**
849 * Send cancellation packet via ring buffer
850 *
851 * @v vmdev VMBus device
852 * @v xid Transaction ID
853 * @ret rc Return status code
854 *
855 * Send data using a VMBUS_CANCELLATION packet.
856 */
858 struct vmbus_packet_header *header = vmdev->packet;
859
860 /* Construct header in packet buffer */
861 assert ( header != NULL );
863 header->hdr_qlen = cpu_to_le16 ( sizeof ( *header ) / 8 );
864 header->flags = 0;
865 header->xid = xid; /* Non-endian */
866
867 return vmbus_send ( vmdev, header, NULL, 0 );
868}
869
870/**
871 * Get transfer page set from pageset ID
872 *
873 * @v vmdev VMBus device
874 * @v pageset Page set ID (in protocol byte order)
875 * @ret pages Page set, or NULL if not found
876 */
877static struct vmbus_xfer_pages * vmbus_xfer_pages ( struct vmbus_device *vmdev,
878 uint16_t pageset ) {
879 struct vmbus_xfer_pages *pages;
880
881 /* Locate page set */
882 list_for_each_entry ( pages, &vmdev->pages, list ) {
883 if ( pages->pageset == pageset )
884 return pages;
885 }
886
887 DBGC ( vmdev, "VMBUS %s unrecognised page set ID %#04x\n",
888 vmdev->dev.name, le16_to_cpu ( pageset ) );
889 return NULL;
890}
891
892/**
893 * Construct I/O buffer list from transfer pages
894 *
895 * @v vmdev VMBus device
896 * @v header Transfer page header
897 * @v list I/O buffer list to populate
898 * @ret rc Return status code
899 */
900static int vmbus_xfer_page_iobufs ( struct vmbus_device *vmdev,
902 struct list_head *list ) {
903 struct vmbus_xfer_page_header *page_header =
905 struct vmbus_xfer_pages *pages;
906 struct io_buffer *iobuf;
907 struct io_buffer *tmp;
908 size_t len;
909 size_t offset;
910 unsigned int range_count;
911 unsigned int i;
912 int rc;
913
914 /* Sanity check */
916
917 /* Locate page set */
918 pages = vmbus_xfer_pages ( vmdev, page_header->pageset );
919 if ( ! pages ) {
920 rc = -ENOENT;
921 goto err_pages;
922 }
923
924 /* Allocate and populate I/O buffers */
925 range_count = le32_to_cpu ( page_header->range_count );
926 for ( i = 0 ; i < range_count ; i++ ) {
927
928 /* Parse header */
929 len = le32_to_cpu ( page_header->range[i].len );
930 offset = le32_to_cpu ( page_header->range[i].offset );
931
932 /* Allocate I/O buffer */
933 iobuf = alloc_iob ( len );
934 if ( ! iobuf ) {
935 DBGC ( vmdev, "VMBUS %s could not allocate %zd-byte "
936 "I/O buffer\n", vmdev->dev.name, len );
937 rc = -ENOMEM;
938 goto err_alloc;
939 }
940
941 /* Add I/O buffer to list */
942 list_add ( &iobuf->list, list );
943
944 /* Populate I/O buffer */
945 if ( ( rc = pages->op->copy ( pages, iob_put ( iobuf, len ),
946 offset, len ) ) != 0 ) {
947 DBGC ( vmdev, "VMBUS %s could not populate I/O buffer "
948 "range [%zd,%zd): %s\n",
949 vmdev->dev.name, offset, len, strerror ( rc ) );
950 goto err_copy;
951 }
952 }
953
954 return 0;
955
956 err_copy:
957 err_alloc:
959 list_del ( &iobuf->list );
960 free_iob ( iobuf );
961 }
962 err_pages:
963 return rc;
964}
965
966/**
967 * Poll ring buffer
968 *
969 * @v vmdev VMBus device
970 * @ret rc Return status code
971 */
972int vmbus_poll ( struct vmbus_device *vmdev ) {
973 struct vmbus_packet_header *header = vmdev->packet;
974 struct list_head list;
975 void *data;
976 size_t header_len;
977 size_t len;
978 size_t footer_len;
979 size_t ring_len;
980 size_t cons;
981 size_t old_cons;
982 uint64_t xid;
983 int rc;
984
985 /* Sanity checks */
986 assert ( vmdev->packet != NULL );
987 assert ( vmdev->in != NULL );
988
989 /* Return immediately if buffer is empty */
990 if ( ! vmbus_has_data ( vmdev ) )
991 return 0;
992 cons = le32_to_cpu ( vmdev->in->cons );
993 old_cons = cons;
994
995 /* Consume (start of) header */
996 cons = vmbus_consume ( vmdev, cons, header, sizeof ( *header ) );
997
998 /* Parse and sanity check header */
999 header_len = ( le16_to_cpu ( header->hdr_qlen ) * 8 );
1000 if ( header_len < sizeof ( *header ) ) {
1001 DBGC ( vmdev, "VMBUS %s received underlength header (%zd "
1002 "bytes)\n", vmdev->dev.name, header_len );
1003 return -EINVAL;
1004 }
1005 len = ( le16_to_cpu ( header->qlen ) * 8 );
1006 if ( len < header_len ) {
1007 DBGC ( vmdev, "VMBUS %s received underlength packet (%zd "
1008 "bytes with %zd-byte header)\n",
1009 vmdev->dev.name, len, header_len );
1010 return -EINVAL;
1011 }
1012 len -= header_len;
1013 footer_len = sizeof ( struct vmbus_packet_footer );
1014 ring_len = ( header_len + len + footer_len );
1015 if ( ring_len > vmdev->mtu ) {
1016 DBGC ( vmdev, "VMBUS %s received overlength packet (%zd "
1017 "bytes)\n", vmdev->dev.name, ring_len );
1018 return -ERANGE;
1019 }
1020 xid = le64_to_cpu ( header->xid );
1021
1022 /* Consume remainder of packet */
1023 cons = vmbus_consume ( vmdev, cons,
1024 ( ( ( void * ) header ) + sizeof ( *header ) ),
1025 ( ring_len - sizeof ( *header ) ) );
1026 DBGC2 ( vmdev, "VMBUS %s received:\n", vmdev->dev.name );
1027 DBGC2_HDA ( vmdev, old_cons, header, ring_len );
1028 assert ( ( ( cons - old_cons ) & ( vmdev->in_len - 1 ) ) == ring_len );
1029
1030 /* Allocate I/O buffers, if applicable */
1031 INIT_LIST_HEAD ( &list );
1032 if ( header->type == cpu_to_le16 ( VMBUS_DATA_XFER_PAGES ) ) {
1033 if ( ( rc = vmbus_xfer_page_iobufs ( vmdev, header,
1034 &list ) ) != 0 )
1035 return rc;
1036 }
1037
1038 /* Update producer index */
1039 rmb();
1040 vmdev->in->cons = cpu_to_le32 ( cons );
1041
1042 /* Handle packet */
1043 data = ( ( ( void * ) header ) + header_len );
1044 switch ( header->type ) {
1045
1047 if ( ( rc = vmdev->op->recv_control ( vmdev, xid, data,
1048 len ) ) != 0 ) {
1049 DBGC ( vmdev, "VMBUS %s could not handle control "
1050 "packet: %s\n",
1051 vmdev->dev.name, strerror ( rc ) );
1052 return rc;
1053 }
1054 break;
1055
1057 if ( ( rc = vmdev->op->recv_data ( vmdev, xid, data, len,
1058 &list ) ) != 0 ) {
1059 DBGC ( vmdev, "VMBUS %s could not handle data packet: "
1060 "%s\n", vmdev->dev.name, strerror ( rc ) );
1061 return rc;
1062 }
1063 break;
1064
1065 case cpu_to_le16 ( VMBUS_COMPLETION ) :
1066 if ( ( rc = vmdev->op->recv_completion ( vmdev, xid, data,
1067 len ) ) != 0 ) {
1068 DBGC ( vmdev, "VMBUS %s could not handle completion: "
1069 "%s\n", vmdev->dev.name, strerror ( rc ) );
1070 return rc;
1071 }
1072 break;
1073
1075 if ( ( rc = vmdev->op->recv_cancellation ( vmdev, xid ) ) != 0){
1076 DBGC ( vmdev, "VMBUS %s could not handle cancellation: "
1077 "%s\n", vmdev->dev.name, strerror ( rc ) );
1078 return rc;
1079 }
1080 break;
1081
1082 default:
1083 DBGC ( vmdev, "VMBUS %s unknown packet type %d\n",
1084 vmdev->dev.name, le16_to_cpu ( header->type ) );
1085 return -ENOTSUP;
1086 }
1087
1088 return 0;
1089}
1090
1091/**
1092 * Dump channel status (for debugging)
1093 *
1094 * @v vmdev VMBus device
1095 */
1096void vmbus_dump_channel ( struct vmbus_device *vmdev ) {
1097 size_t out_prod = le32_to_cpu ( vmdev->out->prod );
1098 size_t out_cons = le32_to_cpu ( vmdev->out->cons );
1099 size_t in_prod = le32_to_cpu ( vmdev->in->prod );
1100 size_t in_cons = le32_to_cpu ( vmdev->in->cons );
1101 size_t in_len;
1102 size_t first;
1103 size_t second;
1104
1105 /* Dump ring status */
1106 DBGC ( vmdev, "VMBUS %s out %03zx:%03zx%s in %03zx:%03zx%s\n",
1107 vmdev->dev.name, out_prod, out_cons,
1108 ( vmdev->out->intr_mask ? "(m)" : "" ), in_prod, in_cons,
1109 ( vmdev->in->intr_mask ? "(m)" : "" ) );
1110
1111 /* Dump inbound ring contents, if any */
1112 if ( in_prod != in_cons ) {
1113 in_len = ( ( in_prod - in_cons ) &
1114 ( vmdev->in_len - 1 ) );
1115 first = ( vmdev->in_len - in_cons );
1116 if ( first > in_len )
1117 first = in_len;
1118 second = ( in_len - first );
1119 DBGC_HDA ( vmdev, in_cons, &vmdev->in->data[in_cons], first );
1120 DBGC_HDA ( vmdev, 0, &vmdev->in->data[0], second );
1121 }
1122}
1123
1124/**
1125 * Find driver for VMBus device
1126 *
1127 * @v vmdev VMBus device
1128 * @ret driver Driver, or NULL
1129 */
1130static struct vmbus_driver * vmbus_find_driver ( const union uuid *type ) {
1131 struct vmbus_driver *vmdrv;
1132
1134 if ( memcmp ( &vmdrv->type, type, sizeof ( *type ) ) == 0 )
1135 return vmdrv;
1136 }
1137 return NULL;
1138}
1139
1140/**
1141 * Probe channels
1142 *
1143 * @v hv Hyper-V hypervisor
1144 * @v parent Parent device
1145 * @ret rc Return status code
1146 */
1147static int vmbus_probe_channels ( struct hv_hypervisor *hv,
1148 struct device *parent ) {
1149 struct vmbus *vmbus = hv->vmbus;
1150 const struct vmbus_message_header *header = &vmbus->message->header;
1151 const struct vmbus_offer_channel *offer = &vmbus->message->offer;
1152 const union uuid *type;
1153 union uuid instance;
1154 struct vmbus_driver *driver;
1155 struct vmbus_device *vmdev;
1156 struct vmbus_device *tmp;
1157 unsigned int channel;
1158 int rc;
1159
1160 /* Post message */
1162 goto err_post_message;
1163
1164 /* Collect responses */
1165 while ( 1 ) {
1166
1167 /* Wait for response */
1168 if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
1169 goto err_wait_for_any_message;
1170
1171 /* Handle response */
1172 if ( header->type == cpu_to_le32 ( VMBUS_OFFER_CHANNEL ) ) {
1173
1174 /* Parse offer */
1175 type = &offer->type;
1176 channel = le32_to_cpu ( offer->channel );
1177 DBGC2 ( vmbus, "VMBUS %p offer %d type %s",
1178 vmbus, channel, uuid_ntoa ( type ) );
1179 if ( offer->monitored )
1180 DBGC2 ( vmbus, " monitor %d", offer->monitor );
1181 DBGC2 ( vmbus, "\n" );
1182
1183 /* Look for a driver */
1185 if ( ! driver ) {
1186 DBGC2 ( vmbus, "VMBUS %p has no driver for "
1187 "type %s\n", vmbus, uuid_ntoa ( type ));
1188 /* Not a fatal error */
1189 continue;
1190 }
1191
1192 /* Allocate and initialise device */
1193 vmdev = zalloc ( sizeof ( *vmdev ) );
1194 if ( ! vmdev ) {
1195 rc = -ENOMEM;
1196 goto err_alloc_vmdev;
1197 }
1198 memcpy ( &instance, &offer->instance,
1199 sizeof ( instance ) );
1200 uuid_mangle ( &instance );
1201 snprintf ( vmdev->dev.name, sizeof ( vmdev->dev.name ),
1202 "{%s}", uuid_ntoa ( &instance ) );
1203 vmdev->dev.desc.bus_type = BUS_TYPE_HV;
1204 INIT_LIST_HEAD ( &vmdev->dev.children );
1205 list_add_tail ( &vmdev->dev.siblings,
1206 &parent->children );
1207 vmdev->dev.parent = parent;
1208 vmdev->hv = hv;
1209 memcpy ( &vmdev->instance, &offer->instance,
1210 sizeof ( vmdev->instance ) );
1211 vmdev->channel = channel;
1212 vmdev->monitor = offer->monitor;
1213 vmdev->signal = ( offer->monitored ?
1216 INIT_LIST_HEAD ( &vmdev->pages );
1217 vmdev->driver = driver;
1218 vmdev->dev.driver_name = driver->name;
1219 DBGC ( vmdev, "VMBUS %s has driver \"%s\"\n",
1220 vmdev->dev.name, vmdev->driver->name );
1221
1222 } else if ( header->type ==
1224
1225 /* End of offer list */
1226 break;
1227
1228 } else {
1229 DBGC ( vmbus, "VMBUS %p unexpected offer response type "
1230 "%d\n", vmbus, le32_to_cpu ( header->type ) );
1231 rc = -EPROTO;
1232 goto err_unexpected_offer;
1233 }
1234 }
1235
1236 /* Probe all devices. We do this only after completing
1237 * enumeration since devices will need to send and receive
1238 * VMBus messages.
1239 */
1240 list_for_each_entry ( vmdev, &parent->children, dev.siblings ) {
1241 if ( ( rc = vmdev->driver->probe ( vmdev ) ) != 0 ) {
1242 DBGC ( vmdev, "VMBUS %s could not probe: %s\n",
1243 vmdev->dev.name, strerror ( rc ) );
1244 goto err_probe;
1245 }
1246 }
1247
1248 return 0;
1249
1250 err_probe:
1251 /* Remove driver from each device that was already probed */
1253 dev.siblings ) {
1254 vmdev->driver->remove ( vmdev );
1255 }
1256 err_unexpected_offer:
1257 err_alloc_vmdev:
1258 err_wait_for_any_message:
1259 /* Free any devices allocated (but potentially not yet probed) */
1260 list_for_each_entry_safe ( vmdev, tmp, &parent->children,
1261 dev.siblings ) {
1262 list_del ( &vmdev->dev.siblings );
1263 free ( vmdev );
1264 }
1265 err_post_message:
1266 return rc;
1267}
1268
1269
1270/**
1271 * Reset channels
1272 *
1273 * @v hv Hyper-V hypervisor
1274 * @v parent Parent device
1275 * @ret rc Return status code
1276 */
1278 struct device *parent ) {
1279 struct vmbus *vmbus = hv->vmbus;
1280 const struct vmbus_message_header *header = &vmbus->message->header;
1281 const struct vmbus_offer_channel *offer = &vmbus->message->offer;
1282 const union uuid *type;
1283 struct vmbus_device *vmdev;
1284 unsigned int channel;
1285 int rc;
1286
1287 /* Post message */
1289 return rc;
1290
1291 /* Collect responses */
1292 while ( 1 ) {
1293
1294 /* Wait for response */
1295 if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
1296 return rc;
1297
1298 /* Handle response */
1299 if ( header->type == cpu_to_le32 ( VMBUS_OFFER_CHANNEL ) ) {
1300
1301 /* Parse offer */
1302 type = &offer->type;
1303 channel = le32_to_cpu ( offer->channel );
1304 DBGC2 ( vmbus, "VMBUS %p offer %d type %s",
1305 vmbus, channel, uuid_ntoa ( type ) );
1306 if ( offer->monitored )
1307 DBGC2 ( vmbus, " monitor %d", offer->monitor );
1308 DBGC2 ( vmbus, "\n" );
1309
1310 /* Do nothing with the offer; we already have all
1311 * of the relevant state from the initial probe.
1312 */
1313
1314 } else if ( header->type ==
1316
1317 /* End of offer list */
1318 break;
1319
1320 } else {
1321 DBGC ( vmbus, "VMBUS %p unexpected offer response type "
1322 "%d\n", vmbus, le32_to_cpu ( header->type ) );
1323 return -EPROTO;
1324 }
1325 }
1326
1327 /* Reset all devices */
1328 list_for_each_entry ( vmdev, &parent->children, dev.siblings ) {
1329 if ( ( rc = vmdev->driver->reset ( vmdev ) ) != 0 ) {
1330 DBGC ( vmdev, "VMBUS %s could not reset: %s\n",
1331 vmdev->dev.name, strerror ( rc ) );
1332 /* Continue attempting to reset other devices */
1333 continue;
1334 }
1335 }
1336
1337 return 0;
1338}
1339
1340/**
1341 * Remove channels
1342 *
1343 * @v hv Hyper-V hypervisor
1344 * @v parent Parent device
1345 */
1347 struct device *parent ) {
1348 struct vmbus_device *vmdev;
1349 struct vmbus_device *tmp;
1350
1351 /* Remove devices */
1352 list_for_each_entry_safe ( vmdev, tmp, &parent->children,
1353 dev.siblings ) {
1354 vmdev->driver->remove ( vmdev );
1355 assert ( list_empty ( &vmdev->dev.children ) );
1356 assert ( vmdev->out == NULL );
1357 assert ( vmdev->in == NULL );
1358 assert ( vmdev->packet == NULL );
1359 assert ( list_empty ( &vmdev->pages ) );
1360 list_del ( &vmdev->dev.siblings );
1361 free ( vmdev );
1362 }
1363}
1364
1365/**
1366 * Probe Hyper-V virtual machine bus
1367 *
1368 * @v hv Hyper-V hypervisor
1369 * @v parent Parent device
1370 * @ret rc Return status code
1371 */
1372int vmbus_probe ( struct hv_hypervisor *hv, struct device *parent ) {
1373 struct vmbus *vmbus;
1374 int rc;
1375
1376 /* Allocate and initialise structure */
1377 vmbus = zalloc ( sizeof ( *vmbus ) );
1378 if ( ! vmbus ) {
1379 rc = -ENOMEM;
1380 goto err_alloc;
1381 }
1382 hv->vmbus = vmbus;
1383
1384 /* Initialise message buffer pointer
1385 *
1386 * We use a pointer to the fixed-size Hyper-V received message
1387 * buffer. This allows us to access fields within received
1388 * messages without first checking the message size: any
1389 * fields beyond the end of the message will read as zero.
1390 */
1391 vmbus->message = ( ( void * ) hv->message->received.data );
1392 assert ( sizeof ( *vmbus->message ) <=
1393 sizeof ( hv->message->received.data ) );
1394
1395 /* Allocate interrupt and monitor pages */
1396 if ( ( rc = hv_alloc_pages ( hv, &vmbus->intr, &vmbus->monitor_in,
1397 &vmbus->monitor_out, NULL ) ) != 0 )
1398 goto err_alloc_pages;
1399
1400 /* Enable message interrupt */
1402
1403 /* Negotiate protocol version */
1404 if ( ( rc = vmbus_negotiate_version ( hv ) ) != 0 )
1405 goto err_negotiate_version;
1406
1407 /* Enumerate channels */
1408 if ( ( rc = vmbus_probe_channels ( hv, parent ) ) != 0 )
1409 goto err_probe_channels;
1410
1411 return 0;
1412
1413 vmbus_remove_channels ( hv, parent );
1414 err_probe_channels:
1415 vmbus_unload ( hv );
1416 err_negotiate_version:
1419 NULL );
1420 err_alloc_pages:
1421 free ( vmbus );
1422 err_alloc:
1423 return rc;
1424}
1425
1426/**
1427 * Reset Hyper-V virtual machine bus
1428 *
1429 * @v hv Hyper-V hypervisor
1430 * @v parent Parent device
1431 * @ret rc Return status code
1432 */
1433int vmbus_reset ( struct hv_hypervisor *hv, struct device *parent ) {
1434 struct vmbus *vmbus = hv->vmbus;
1435 int rc;
1436
1437 /* Mark all existent GPADLs as obsolete */
1439
1440 /* Clear interrupt and monitor pages */
1441 memset ( vmbus->intr, 0, PAGE_SIZE );
1444
1445 /* Enable message interrupt */
1447
1448 /* Renegotiate protocol version */
1449 if ( ( rc = vmbus_negotiate_version ( hv ) ) != 0 )
1450 return rc;
1451
1452 /* Reenumerate channels */
1453 if ( ( rc = vmbus_reset_channels ( hv, parent ) ) != 0 )
1454 return rc;
1455
1456 return 0;
1457}
1458
1459/**
1460 * Remove Hyper-V virtual machine bus
1461 *
1462 * @v hv Hyper-V hypervisor
1463 * @v parent Parent device
1464 */
1465void vmbus_remove ( struct hv_hypervisor *hv, struct device *parent ) {
1466 struct vmbus *vmbus = hv->vmbus;
1467
1468 vmbus_remove_channels ( hv, parent );
1469 vmbus_unload ( hv );
1472 NULL );
1473 free ( vmbus );
1474}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
__be32 raw[7]
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
unsigned long physaddr_t
Definition stdint.h:20
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
static int fill
Definition string.h:209
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
u32 version
Driver version.
Definition ath9k_hw.c:1985
uint16_t offset
Offset to command line.
Definition bzimage.h:3
#define BUS_TYPE_HV
Hyper-V bus type.
Definition device.h:68
ring len
Length.
Definition dwmac.h:226
uint32_t addr
Buffer address.
Definition dwmac.h:9
uint16_t cons
Consumer index.
Definition ena.h:11
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint32_t mtu
Maximum MTU.
Definition ena.h:17
struct ena_llq_option header
Header locations.
Definition ena.h:5
uint16_t group
Type of event.
Definition ena.h:1
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define ENOENT
No such file or directory.
Definition errno.h:558
#define EINVAL
Invalid argument.
Definition errno.h:472
#define EPROTO
Protocol error.
Definition errno.h:668
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ENOBUFS
No buffer space available.
Definition errno.h:542
int hv_wait_for_message(struct hv_hypervisor *hv, unsigned int sintx)
Wait for received message.
Definition hyperv.c:486
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
Definition hyperv.c:423
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
Definition hyperv.c:113
int hv_alloc_pages(struct hv_hypervisor *hv,...)
Allocate zeroed pages.
Definition hyperv.c:78
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
Definition hyperv.c:397
#define le16_to_cpu(value)
Definition byteswap.h:113
#define le64_to_cpu(value)
Definition byteswap.h:115
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
#define cpu_to_le16(value)
Definition byteswap.h:107
#define __attribute__(x)
Definition compiler.h:10
static unsigned int unsigned int bit
Definition bigint.h:390
Bit operations.
Hyper-V interface.
struct hv_monitor_trigger trigger[4]
Trigger groups.
Definition hyperv.h:5
static unsigned int hv_pfn_count(physaddr_t data, size_t len)
Calculate the number of pages covering an address range.
Definition hyperv.h:223
#define rmb()
Definition io.h:545
void mb(void)
Memory barrier.
#define wmb()
Definition io.h:546
#define PAGE_SIZE
Page size.
Definition io.h:28
CPU sleeping.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define iob_put(iobuf, len)
Definition iobuf.h:185
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_continue_reverse(pos, head, member)
Iterate over entries in a list in reverse, starting after current position.
Definition list.h:487
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition malloc.c:789
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys().
Definition malloc.c:805
Dynamic memory allocation.
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
uint16_t pageset
Page set ID.
Definition netvsc.h:5
uint32_t gpadl
GPADL ID.
Definition netvsc.h:3
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
uint32_t first
First block in range.
Definition pccrr.h:1
struct pci_range range
PCI bus:dev.fn address range.
Definition pcicloud.c:40
int open(const char *uri_string)
Open file.
Definition posix_io.c:176
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
unsigned int bus_type
Bus type.
Definition device.h:25
A hardware device.
Definition device.h:77
struct device_description desc
Device description.
Definition device.h:83
struct device * parent
Bus device.
Definition device.h:89
struct list_head children
Devices attached to this device.
Definition device.h:87
struct list_head siblings
Devices on the same bus.
Definition device.h:85
const char * driver_name
Driver name.
Definition device.h:81
char name[40]
Name.
Definition device.h:79
A Hyper-V hypervisor.
Definition hyperv.h:203
union hv_message_buffer * message
Message buffer.
Definition hyperv.h:209
struct vmbus * vmbus
Virtual machine bus.
Definition hyperv.h:211
uint8_t data[240]
Message.
Definition hyperv.h:112
uint32_t type
Type.
Definition hyperv.h:102
A monitor trigger group.
Definition hyperv.h:139
struct hv_monitor_trigger trigger[4]
Trigger groups.
Definition hyperv.h:171
A posted message.
Definition hyperv.h:81
A signalled event.
Definition hyperv.h:119
A persistent I/O buffer.
Definition iobuf.h:98
void * data
Start of data.
Definition iobuf.h:113
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:105
A doubly-linked list entry (or list head).
Definition list.h:19
VMBus channel operations.
Definition vmbus.h:396
int(* recv_completion)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received completion packet.
Definition vmbus.h:434
int(* recv_data)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct list_head *list)
Handle received data packet.
Definition vmbus.h:422
int(* recv_cancellation)(struct vmbus_device *vmdev, uint64_t xid)
Handle received cancellation packet.
Definition vmbus.h:443
int(* recv_control)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received control packet.
Definition vmbus.h:406
VMBus "close channel" message.
Definition vmbus.h:157
A VMBus device.
Definition vmbus.h:475
void(* signal)(struct vmbus_device *vmdev)
Signal channel.
Definition vmbus.h:491
void * packet
Packet buffer.
Definition vmbus.h:509
struct vmbus_ring * in
Inbound ring buffer.
Definition vmbus.h:500
unsigned int gpadl
Ring buffer GPADL ID.
Definition vmbus.h:502
struct vmbus_channel_operations * op
Channel operations.
Definition vmbus.h:505
struct vmbus_driver * driver
Driver.
Definition vmbus.h:514
uint32_t out_len
Outbound ring buffer length.
Definition vmbus.h:494
unsigned int monitor
Monitor ID.
Definition vmbus.h:486
struct vmbus_ring * out
Outbound ring buffer.
Definition vmbus.h:498
union uuid instance
Channel instance.
Definition vmbus.h:482
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition vmbus.h:479
struct list_head pages
List of transfer page sets.
Definition vmbus.h:511
size_t mtu
Maximum expected data packet length.
Definition vmbus.h:507
unsigned int channel
Channel ID.
Definition vmbus.h:484
uint32_t in_len
Inbound ring buffer length.
Definition vmbus.h:496
struct device dev
Generic iPXE device.
Definition vmbus.h:477
A VMBus device driver.
Definition vmbus.h:520
int(* probe)(struct vmbus_device *vmdev)
Probe device.
Definition vmbus.h:530
int(* reset)(struct vmbus_device *vmdev)
Reset device.
Definition vmbus.h:536
void(* remove)(struct vmbus_device *vmdev)
Remove device.
Definition vmbus.h:541
const char * name
Name.
Definition vmbus.h:522
union uuid type
Device type.
Definition vmbus.h:524
VMBus GPA direct header.
Definition vmbus.h:297
Guest physical address range descriptor.
Definition vmbus.h:57
VMBus "GPADL created" message.
Definition vmbus.h:181
uint32_t channel
Channel ID.
Definition vmbus.h:185
uint32_t gpadl
GPADL ID.
Definition vmbus.h:187
uint32_t status
Creation status.
Definition vmbus.h:189
VMBus "GPADL header" message.
Definition vmbus.h:165
VMBus "GPADL teardown" message.
Definition vmbus.h:193
struct vmbus_message_header header
Message header.
Definition vmbus.h:195
uint32_t channel
Channel ID.
Definition vmbus.h:197
uint32_t gpadl
GPADL ID.
Definition vmbus.h:199
VMBus "GPADL torndown" message.
Definition vmbus.h:203
uint32_t gpadl
GPADL ID.
Definition vmbus.h:207
VMBus "initiate contact" message.
Definition vmbus.h:211
struct vmbus_message_header header
Message header.
Definition vmbus.h:213
union vmbus_version version
Requested version.
Definition vmbus.h:215
uint64_t monitor_in
Parent to child monitor page base address.
Definition vmbus.h:221
uint64_t intr
Interrupt page base address.
Definition vmbus.h:219
uint64_t monitor_out
Child to parent monitor page base address.
Definition vmbus.h:223
uint8_t out[PAGE_SIZE/2]
Outbound interrupts.
Definition vmbus.h:378
VMBus message header.
Definition vmbus.h:71
uint32_t type
Message type.
Definition vmbus.h:73
VMBus "offer channel" message.
Definition vmbus.h:97
union uuid type
Channel type.
Definition vmbus.h:101
union uuid instance
Channel instance.
Definition vmbus.h:103
uint8_t monitor
Monitor ID.
Definition vmbus.h:117
uint8_t monitored
Monitor exists.
Definition vmbus.h:119
uint32_t channel
Channel ID.
Definition vmbus.h:115
VMBus "open channel result" message.
Definition vmbus.h:145
uint32_t status
Status.
Definition vmbus.h:153
uint32_t channel
Channel ID.
Definition vmbus.h:149
uint32_t id
Open ID.
Definition vmbus.h:151
VMBus "open channel" message.
Definition vmbus.h:127
VMBus packet header.
Definition vmbus.h:265
uint64_t xid
Transaction ID.
Definition vmbus.h:279
uint32_t intr_mask
Interrupt mask.
Definition vmbus.h:366
uint8_t data[0]
Ring buffer contents.
Definition vmbus.h:370
uint32_t cons
Consumer index (modulo ring length).
Definition vmbus.h:364
uint32_t prod
Producer index (modulo ring length).
Definition vmbus.h:362
VMBus "version response" message.
Definition vmbus.h:227
VMBus transfer page header.
Definition vmbus.h:317
uint32_t range_count
Number of range descriptors.
Definition vmbus.h:327
uint16_t pageset
Page set ID.
Definition vmbus.h:321
struct vmbus_xfer_page_range range[0]
Range descriptors.
Definition vmbus.h:329
uint32_t len
Length.
Definition vmbus.h:311
uint32_t offset
Offset.
Definition vmbus.h:313
int(* copy)(struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
Copy data from transfer page.
Definition vmbus.h:460
VMBus transfer page set.
Definition vmbus.h:465
struct vmbus_xfer_pages_operations * op
Page set operations.
Definition vmbus.h:471
struct list_head list
List of all transfer page sets.
Definition vmbus.h:467
uint16_t pageset
Page set ID (in protocol byte order).
Definition vmbus.h:469
A virtual machine bus.
Definition vmbus.h:382
struct vmbus_interrupt * intr
Interrupt page.
Definition vmbus.h:384
struct hv_monitor * monitor_out
Outbound notifications.
Definition vmbus.h:388
const union vmbus_message * message
Received message buffer.
Definition vmbus.h:390
struct hv_monitor * monitor_in
Inbound notifications.
Definition vmbus.h:386
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
struct hv_message received
Received message.
Definition hyperv.h:197
A universally unique ID.
Definition uuid.h:16
struct vmbus_message_header header
Common message header.
Definition vmbus.h:241
struct vmbus_gpadl_created created
"GPADL created" message
Definition vmbus.h:253
struct vmbus_gpadl_torndown torndown
"GPADL torndown" message
Definition vmbus.h:257
struct vmbus_open_channel_result opened
"Open channel result" message
Definition vmbus.h:247
struct vmbus_offer_channel offer
"Offer channel" message
Definition vmbus.h:243
struct vmbus_version_response version
"Version response" message
Definition vmbus.h:261
uint32_t raw
Raw version.
Definition vmbus.h:34
uint16_t minor
Minor version.
Definition vmbus.h:38
uint16_t major
Major version.
Definition vmbus.h:40
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition uuid.c:46
static void uuid_mangle(union uuid *uuid)
Change UUID endianness.
Definition uuid.h:44
static void vmbus_remove_channels(struct hv_hypervisor *hv __unused, struct device *parent)
Remove channels.
Definition vmbus.c:1346
int vmbus_send_data(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct io_buffer *iobuf)
Send data packet via ring buffer.
Definition vmbus.c:794
void vmbus_close(struct vmbus_device *vmdev)
Close VMBus channel.
Definition vmbus.c:524
int vmbus_probe(struct hv_hypervisor *hv, struct device *parent)
Probe Hyper-V virtual machine bus.
Definition vmbus.c:1372
static void vmbus_signal_monitor(struct vmbus_device *vmdev)
Signal channel via monitor page.
Definition vmbus.c:574
int vmbus_send_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send control packet via ring buffer.
Definition vmbus.c:765
static void vmbus_signal_event(struct vmbus_device *vmdev)
Signal channel via hypervisor event.
Definition vmbus.c:593
void vmbus_remove(struct hv_hypervisor *hv, struct device *parent)
Remove Hyper-V virtual machine bus.
Definition vmbus.c:1465
int vmbus_send_completion(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send completion packet via ring buffer.
Definition vmbus.c:834
int vmbus_send_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Send cancellation packet via ring buffer.
Definition vmbus.c:857
static int vmbus_wait_for_message(struct hv_hypervisor *hv, unsigned int type)
Wait for received message of a specified type, ignoring any others.
Definition vmbus.c:136
unsigned int vmbus_obsolete_gpadl
Obsolete GPADL ID threshold.
Definition vmbus.c:61
static int vmbus_probe_channels(struct hv_hypervisor *hv, struct device *parent)
Probe channels.
Definition vmbus.c:1147
static int vmbus_post_empty_message(struct hv_hypervisor *hv, unsigned int type)
Post empty message.
Definition vmbus.c:95
static size_t vmbus_produce(struct vmbus_device *vmdev, size_t prod, const void *data, size_t len)
Fill outbound ring buffer.
Definition vmbus.c:617
void vmbus_dump_channel(struct vmbus_device *vmdev)
Dump channel status (for debugging).
Definition vmbus.c:1096
static int vmbus_send(struct vmbus_device *vmdev, struct vmbus_packet_header *header, const void *data, size_t len)
Send packet via ring buffer.
Definition vmbus.c:677
static int vmbus_initiate_contact(struct hv_hypervisor *hv, unsigned int raw)
Initiate contact.
Definition vmbus.c:168
static int vmbus_negotiate_version(struct hv_hypervisor *hv)
Negotiate protocol version.
Definition vmbus.c:231
static struct vmbus_xfer_pages * vmbus_xfer_pages(struct vmbus_device *vmdev, uint16_t pageset)
Get transfer page set from pageset ID.
Definition vmbus.c:877
static int vmbus_wait_for_any_message(struct hv_hypervisor *hv)
Wait for received message of any type.
Definition vmbus.c:108
int vmbus_reset(struct hv_hypervisor *hv, struct device *parent)
Reset Hyper-V virtual machine bus.
Definition vmbus.c:1433
static struct vmbus_driver * vmbus_find_driver(const union uuid *type)
Find driver for VMBus device.
Definition vmbus.c:1130
static size_t vmbus_consume(struct vmbus_device *vmdev, size_t cons, void *data, size_t len)
Consume inbound ring buffer.
Definition vmbus.c:645
int vmbus_establish_gpadl(struct vmbus_device *vmdev, void *data, size_t len)
Establish GPA descriptor list.
Definition vmbus.c:276
static unsigned int vmbus_gpadl
Current (i.e.
Definition vmbus.c:54
static int vmbus_unload(struct hv_hypervisor *hv)
Terminate contact.
Definition vmbus.c:211
int vmbus_open(struct vmbus_device *vmdev, struct vmbus_channel_operations *op, size_t out_len, size_t in_len, size_t mtu)
Open VMBus channel.
Definition vmbus.c:403
#define VMBUS_GPADL_MAGIC
VMBus initial GPADL ID.
Definition vmbus.c:51
static int vmbus_reset_channels(struct hv_hypervisor *hv, struct device *parent)
Reset channels.
Definition vmbus.c:1277
int vmbus_poll(struct vmbus_device *vmdev)
Poll ring buffer.
Definition vmbus.c:972
int vmbus_gpadl_teardown(struct vmbus_device *vmdev, unsigned int gpadl)
Tear down GPA descriptor list.
Definition vmbus.c:347
static int vmbus_xfer_page_iobufs(struct vmbus_device *vmdev, struct vmbus_packet_header *header, struct list_head *list)
Construct I/O buffer list from transfer pages.
Definition vmbus.c:900
static int vmbus_post_message(struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
Post message.
Definition vmbus.c:71
Hyper-V virtual machine bus.
@ VMBUS_DATA_INBAND
Definition vmbus.h:284
@ VMBUS_COMPLETION
Definition vmbus.h:288
@ VMBUS_DATA_XFER_PAGES
Definition vmbus.h:285
@ VMBUS_CANCELLATION
Definition vmbus.h:287
@ VMBUS_DATA_GPA_DIRECT
Definition vmbus.h:286
@ VMBUS_OPEN_CHANNEL_RESULT
Definition vmbus.h:84
@ VMBUS_GPADL_CREATED
Definition vmbus.h:87
@ VMBUS_REQUEST_OFFERS
Definition vmbus.h:81
@ VMBUS_INITIATE_CONTACT
Definition vmbus.h:90
@ VMBUS_GPADL_TORNDOWN
Definition vmbus.h:89
@ VMBUS_OPEN_CHANNEL
Definition vmbus.h:83
@ VMBUS_OFFER_CHANNEL
Definition vmbus.h:80
@ VMBUS_UNLOAD_RESPONSE
Definition vmbus.h:93
@ VMBUS_UNLOAD
Definition vmbus.h:92
@ VMBUS_GPADL_HEADER
Definition vmbus.h:86
@ VMBUS_VERSION_RESPONSE
Definition vmbus.h:91
@ VMBUS_ALL_OFFERS_DELIVERED
Definition vmbus.h:82
@ VMBUS_GPADL_TEARDOWN
Definition vmbus.h:88
@ VMBUS_CLOSE_CHANNEL
Definition vmbus.h:85
#define VMBUS_DRIVERS
VMBus device driver table.
Definition vmbus.h:545
static int vmbus_gpadl_is_obsolete(unsigned int gpadl)
Check if GPADL is obsolete.
Definition vmbus.h:634
static int vmbus_has_data(struct vmbus_device *vmdev)
Check if data is present in ring buffer.
Definition vmbus.h:588
#define VMBUS_MESSAGE_ID
VMBus message connection ID.
Definition vmbus.h:20
#define VMBUS_MESSAGE_SINT
VMBus message synthetic interrupt.
Definition vmbus.h:29
@ VMBUS_VERSION_WIN8_1
Windows 8.1.
Definition vmbus.h:53
@ VMBUS_VERSION_WS2008
Windows Server 2008.
Definition vmbus.h:47
#define VMBUS_MESSAGE_TYPE
VMBus message type.
Definition vmbus.h:26
@ VMBUS_COMPLETION_REQUESTED
Definition vmbus.h:293
#define VMBUS_EVENT_ID
VMBus event connection ID.
Definition vmbus.h:23
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
#define set_bit(bit, loc)
Definition vxge_main.h:166
static struct evtchn_close * close
Definition xenevent.h:24