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 ) - header_len );
1006 footer_len = sizeof ( struct vmbus_packet_footer );
1007 ring_len = ( header_len + len + footer_len );
1008 if ( ring_len > vmdev->mtu ) {
1009 DBGC ( vmdev, "VMBUS %s received overlength packet (%zd "
1010 "bytes)\n", vmdev->dev.name, ring_len );
1011 return -ERANGE;
1012 }
1013 xid = le64_to_cpu ( header->xid );
1014
1015 /* Consume remainder of packet */
1016 cons = vmbus_consume ( vmdev, cons,
1017 ( ( ( void * ) header ) + sizeof ( *header ) ),
1018 ( ring_len - sizeof ( *header ) ) );
1019 DBGC2 ( vmdev, "VMBUS %s received:\n", vmdev->dev.name );
1020 DBGC2_HDA ( vmdev, old_cons, header, ring_len );
1021 assert ( ( ( cons - old_cons ) & ( vmdev->in_len - 1 ) ) == ring_len );
1022
1023 /* Allocate I/O buffers, if applicable */
1024 INIT_LIST_HEAD ( &list );
1025 if ( header->type == cpu_to_le16 ( VMBUS_DATA_XFER_PAGES ) ) {
1026 if ( ( rc = vmbus_xfer_page_iobufs ( vmdev, header,
1027 &list ) ) != 0 )
1028 return rc;
1029 }
1030
1031 /* Update producer index */
1032 rmb();
1033 vmdev->in->cons = cpu_to_le32 ( cons );
1034
1035 /* Handle packet */
1036 data = ( ( ( void * ) header ) + header_len );
1037 switch ( header->type ) {
1038
1040 if ( ( rc = vmdev->op->recv_control ( vmdev, xid, data,
1041 len ) ) != 0 ) {
1042 DBGC ( vmdev, "VMBUS %s could not handle control "
1043 "packet: %s\n",
1044 vmdev->dev.name, strerror ( rc ) );
1045 return rc;
1046 }
1047 break;
1048
1050 if ( ( rc = vmdev->op->recv_data ( vmdev, xid, data, len,
1051 &list ) ) != 0 ) {
1052 DBGC ( vmdev, "VMBUS %s could not handle data packet: "
1053 "%s\n", vmdev->dev.name, strerror ( rc ) );
1054 return rc;
1055 }
1056 break;
1057
1058 case cpu_to_le16 ( VMBUS_COMPLETION ) :
1059 if ( ( rc = vmdev->op->recv_completion ( vmdev, xid, data,
1060 len ) ) != 0 ) {
1061 DBGC ( vmdev, "VMBUS %s could not handle completion: "
1062 "%s\n", vmdev->dev.name, strerror ( rc ) );
1063 return rc;
1064 }
1065 break;
1066
1068 if ( ( rc = vmdev->op->recv_cancellation ( vmdev, xid ) ) != 0){
1069 DBGC ( vmdev, "VMBUS %s could not handle cancellation: "
1070 "%s\n", vmdev->dev.name, strerror ( rc ) );
1071 return rc;
1072 }
1073 break;
1074
1075 default:
1076 DBGC ( vmdev, "VMBUS %s unknown packet type %d\n",
1077 vmdev->dev.name, le16_to_cpu ( header->type ) );
1078 return -ENOTSUP;
1079 }
1080
1081 return 0;
1082}
1083
1084/**
1085 * Dump channel status (for debugging)
1086 *
1087 * @v vmdev VMBus device
1088 */
1089void vmbus_dump_channel ( struct vmbus_device *vmdev ) {
1090 size_t out_prod = le32_to_cpu ( vmdev->out->prod );
1091 size_t out_cons = le32_to_cpu ( vmdev->out->cons );
1092 size_t in_prod = le32_to_cpu ( vmdev->in->prod );
1093 size_t in_cons = le32_to_cpu ( vmdev->in->cons );
1094 size_t in_len;
1095 size_t first;
1096 size_t second;
1097
1098 /* Dump ring status */
1099 DBGC ( vmdev, "VMBUS %s out %03zx:%03zx%s in %03zx:%03zx%s\n",
1100 vmdev->dev.name, out_prod, out_cons,
1101 ( vmdev->out->intr_mask ? "(m)" : "" ), in_prod, in_cons,
1102 ( vmdev->in->intr_mask ? "(m)" : "" ) );
1103
1104 /* Dump inbound ring contents, if any */
1105 if ( in_prod != in_cons ) {
1106 in_len = ( ( in_prod - in_cons ) &
1107 ( vmdev->in_len - 1 ) );
1108 first = ( vmdev->in_len - in_cons );
1109 if ( first > in_len )
1110 first = in_len;
1111 second = ( in_len - first );
1112 DBGC_HDA ( vmdev, in_cons, &vmdev->in->data[in_cons], first );
1113 DBGC_HDA ( vmdev, 0, &vmdev->in->data[0], second );
1114 }
1115}
1116
1117/**
1118 * Find driver for VMBus device
1119 *
1120 * @v vmdev VMBus device
1121 * @ret driver Driver, or NULL
1122 */
1123static struct vmbus_driver * vmbus_find_driver ( const union uuid *type ) {
1124 struct vmbus_driver *vmdrv;
1125
1127 if ( memcmp ( &vmdrv->type, type, sizeof ( *type ) ) == 0 )
1128 return vmdrv;
1129 }
1130 return NULL;
1131}
1132
1133/**
1134 * Probe channels
1135 *
1136 * @v hv Hyper-V hypervisor
1137 * @v parent Parent device
1138 * @ret rc Return status code
1139 */
1140static int vmbus_probe_channels ( struct hv_hypervisor *hv,
1141 struct device *parent ) {
1142 struct vmbus *vmbus = hv->vmbus;
1143 const struct vmbus_message_header *header = &vmbus->message->header;
1144 const struct vmbus_offer_channel *offer = &vmbus->message->offer;
1145 const union uuid *type;
1146 union uuid instance;
1147 struct vmbus_driver *driver;
1148 struct vmbus_device *vmdev;
1149 struct vmbus_device *tmp;
1150 unsigned int channel;
1151 int rc;
1152
1153 /* Post message */
1155 goto err_post_message;
1156
1157 /* Collect responses */
1158 while ( 1 ) {
1159
1160 /* Wait for response */
1161 if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
1162 goto err_wait_for_any_message;
1163
1164 /* Handle response */
1165 if ( header->type == cpu_to_le32 ( VMBUS_OFFER_CHANNEL ) ) {
1166
1167 /* Parse offer */
1168 type = &offer->type;
1169 channel = le32_to_cpu ( offer->channel );
1170 DBGC2 ( vmbus, "VMBUS %p offer %d type %s",
1171 vmbus, channel, uuid_ntoa ( type ) );
1172 if ( offer->monitored )
1173 DBGC2 ( vmbus, " monitor %d", offer->monitor );
1174 DBGC2 ( vmbus, "\n" );
1175
1176 /* Look for a driver */
1178 if ( ! driver ) {
1179 DBGC2 ( vmbus, "VMBUS %p has no driver for "
1180 "type %s\n", vmbus, uuid_ntoa ( type ));
1181 /* Not a fatal error */
1182 continue;
1183 }
1184
1185 /* Allocate and initialise device */
1186 vmdev = zalloc ( sizeof ( *vmdev ) );
1187 if ( ! vmdev ) {
1188 rc = -ENOMEM;
1189 goto err_alloc_vmdev;
1190 }
1191 memcpy ( &instance, &offer->instance,
1192 sizeof ( instance ) );
1193 uuid_mangle ( &instance );
1194 snprintf ( vmdev->dev.name, sizeof ( vmdev->dev.name ),
1195 "{%s}", uuid_ntoa ( &instance ) );
1196 vmdev->dev.desc.bus_type = BUS_TYPE_HV;
1197 INIT_LIST_HEAD ( &vmdev->dev.children );
1198 list_add_tail ( &vmdev->dev.siblings,
1199 &parent->children );
1200 vmdev->dev.parent = parent;
1201 vmdev->hv = hv;
1202 memcpy ( &vmdev->instance, &offer->instance,
1203 sizeof ( vmdev->instance ) );
1204 vmdev->channel = channel;
1205 vmdev->monitor = offer->monitor;
1206 vmdev->signal = ( offer->monitored ?
1209 INIT_LIST_HEAD ( &vmdev->pages );
1210 vmdev->driver = driver;
1211 vmdev->dev.driver_name = driver->name;
1212 DBGC ( vmdev, "VMBUS %s has driver \"%s\"\n",
1213 vmdev->dev.name, vmdev->driver->name );
1214
1215 } else if ( header->type ==
1217
1218 /* End of offer list */
1219 break;
1220
1221 } else {
1222 DBGC ( vmbus, "VMBUS %p unexpected offer response type "
1223 "%d\n", vmbus, le32_to_cpu ( header->type ) );
1224 rc = -EPROTO;
1225 goto err_unexpected_offer;
1226 }
1227 }
1228
1229 /* Probe all devices. We do this only after completing
1230 * enumeration since devices will need to send and receive
1231 * VMBus messages.
1232 */
1233 list_for_each_entry ( vmdev, &parent->children, dev.siblings ) {
1234 if ( ( rc = vmdev->driver->probe ( vmdev ) ) != 0 ) {
1235 DBGC ( vmdev, "VMBUS %s could not probe: %s\n",
1236 vmdev->dev.name, strerror ( rc ) );
1237 goto err_probe;
1238 }
1239 }
1240
1241 return 0;
1242
1243 err_probe:
1244 /* Remove driver from each device that was already probed */
1246 dev.siblings ) {
1247 vmdev->driver->remove ( vmdev );
1248 }
1249 err_unexpected_offer:
1250 err_alloc_vmdev:
1251 err_wait_for_any_message:
1252 /* Free any devices allocated (but potentially not yet probed) */
1253 list_for_each_entry_safe ( vmdev, tmp, &parent->children,
1254 dev.siblings ) {
1255 list_del ( &vmdev->dev.siblings );
1256 free ( vmdev );
1257 }
1258 err_post_message:
1259 return rc;
1260}
1261
1262
1263/**
1264 * Reset channels
1265 *
1266 * @v hv Hyper-V hypervisor
1267 * @v parent Parent device
1268 * @ret rc Return status code
1269 */
1271 struct device *parent ) {
1272 struct vmbus *vmbus = hv->vmbus;
1273 const struct vmbus_message_header *header = &vmbus->message->header;
1274 const struct vmbus_offer_channel *offer = &vmbus->message->offer;
1275 const union uuid *type;
1276 struct vmbus_device *vmdev;
1277 unsigned int channel;
1278 int rc;
1279
1280 /* Post message */
1282 return rc;
1283
1284 /* Collect responses */
1285 while ( 1 ) {
1286
1287 /* Wait for response */
1288 if ( ( rc = vmbus_wait_for_any_message ( hv ) ) != 0 )
1289 return rc;
1290
1291 /* Handle response */
1292 if ( header->type == cpu_to_le32 ( VMBUS_OFFER_CHANNEL ) ) {
1293
1294 /* Parse offer */
1295 type = &offer->type;
1296 channel = le32_to_cpu ( offer->channel );
1297 DBGC2 ( vmbus, "VMBUS %p offer %d type %s",
1298 vmbus, channel, uuid_ntoa ( type ) );
1299 if ( offer->monitored )
1300 DBGC2 ( vmbus, " monitor %d", offer->monitor );
1301 DBGC2 ( vmbus, "\n" );
1302
1303 /* Do nothing with the offer; we already have all
1304 * of the relevant state from the initial probe.
1305 */
1306
1307 } else if ( header->type ==
1309
1310 /* End of offer list */
1311 break;
1312
1313 } else {
1314 DBGC ( vmbus, "VMBUS %p unexpected offer response type "
1315 "%d\n", vmbus, le32_to_cpu ( header->type ) );
1316 return -EPROTO;
1317 }
1318 }
1319
1320 /* Reset all devices */
1321 list_for_each_entry ( vmdev, &parent->children, dev.siblings ) {
1322 if ( ( rc = vmdev->driver->reset ( vmdev ) ) != 0 ) {
1323 DBGC ( vmdev, "VMBUS %s could not reset: %s\n",
1324 vmdev->dev.name, strerror ( rc ) );
1325 /* Continue attempting to reset other devices */
1326 continue;
1327 }
1328 }
1329
1330 return 0;
1331}
1332
1333/**
1334 * Remove channels
1335 *
1336 * @v hv Hyper-V hypervisor
1337 * @v parent Parent device
1338 */
1340 struct device *parent ) {
1341 struct vmbus_device *vmdev;
1342 struct vmbus_device *tmp;
1343
1344 /* Remove devices */
1345 list_for_each_entry_safe ( vmdev, tmp, &parent->children,
1346 dev.siblings ) {
1347 vmdev->driver->remove ( vmdev );
1348 assert ( list_empty ( &vmdev->dev.children ) );
1349 assert ( vmdev->out == NULL );
1350 assert ( vmdev->in == NULL );
1351 assert ( vmdev->packet == NULL );
1352 assert ( list_empty ( &vmdev->pages ) );
1353 list_del ( &vmdev->dev.siblings );
1354 free ( vmdev );
1355 }
1356}
1357
1358/**
1359 * Probe Hyper-V virtual machine bus
1360 *
1361 * @v hv Hyper-V hypervisor
1362 * @v parent Parent device
1363 * @ret rc Return status code
1364 */
1365int vmbus_probe ( struct hv_hypervisor *hv, struct device *parent ) {
1366 struct vmbus *vmbus;
1367 int rc;
1368
1369 /* Allocate and initialise structure */
1370 vmbus = zalloc ( sizeof ( *vmbus ) );
1371 if ( ! vmbus ) {
1372 rc = -ENOMEM;
1373 goto err_alloc;
1374 }
1375 hv->vmbus = vmbus;
1376
1377 /* Initialise message buffer pointer
1378 *
1379 * We use a pointer to the fixed-size Hyper-V received message
1380 * buffer. This allows us to access fields within received
1381 * messages without first checking the message size: any
1382 * fields beyond the end of the message will read as zero.
1383 */
1384 vmbus->message = ( ( void * ) hv->message->received.data );
1385 assert ( sizeof ( *vmbus->message ) <=
1386 sizeof ( hv->message->received.data ) );
1387
1388 /* Allocate interrupt and monitor pages */
1389 if ( ( rc = hv_alloc_pages ( hv, &vmbus->intr, &vmbus->monitor_in,
1390 &vmbus->monitor_out, NULL ) ) != 0 )
1391 goto err_alloc_pages;
1392
1393 /* Enable message interrupt */
1395
1396 /* Negotiate protocol version */
1397 if ( ( rc = vmbus_negotiate_version ( hv ) ) != 0 )
1398 goto err_negotiate_version;
1399
1400 /* Enumerate channels */
1401 if ( ( rc = vmbus_probe_channels ( hv, parent ) ) != 0 )
1402 goto err_probe_channels;
1403
1404 return 0;
1405
1406 vmbus_remove_channels ( hv, parent );
1407 err_probe_channels:
1408 vmbus_unload ( hv );
1409 err_negotiate_version:
1412 NULL );
1413 err_alloc_pages:
1414 free ( vmbus );
1415 err_alloc:
1416 return rc;
1417}
1418
1419/**
1420 * Reset Hyper-V virtual machine bus
1421 *
1422 * @v hv Hyper-V hypervisor
1423 * @v parent Parent device
1424 * @ret rc Return status code
1425 */
1426int vmbus_reset ( struct hv_hypervisor *hv, struct device *parent ) {
1427 struct vmbus *vmbus = hv->vmbus;
1428 int rc;
1429
1430 /* Mark all existent GPADLs as obsolete */
1432
1433 /* Clear interrupt and monitor pages */
1434 memset ( vmbus->intr, 0, PAGE_SIZE );
1437
1438 /* Enable message interrupt */
1440
1441 /* Renegotiate protocol version */
1442 if ( ( rc = vmbus_negotiate_version ( hv ) ) != 0 )
1443 return rc;
1444
1445 /* Reenumerate channels */
1446 if ( ( rc = vmbus_reset_channels ( hv, parent ) ) != 0 )
1447 return rc;
1448
1449 return 0;
1450}
1451
1452/**
1453 * Remove Hyper-V virtual machine bus
1454 *
1455 * @v hv Hyper-V hypervisor
1456 * @v parent Parent device
1457 */
1458void vmbus_remove ( struct hv_hypervisor *hv, struct device *parent ) {
1459 struct vmbus *vmbus = hv->vmbus;
1460
1461 vmbus_remove_channels ( hv, parent );
1462 vmbus_unload ( hv );
1465 NULL );
1466 free ( vmbus );
1467}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__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
long pad_len
Definition bigint.h:31
static int fill
Definition string.h:209
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
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:573
#define DBGC2(...)
Definition compiler.h:522
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EPROTO
Protocol error.
Definition errno.h:625
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ENOBUFS
No buffer space available.
Definition errno.h:499
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:392
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:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
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:662
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition malloc.c:707
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Definition malloc.c:723
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:38
void * data
Start of data.
Definition iobuf.h:53
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
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:1339
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:1365
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:1458
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:1140
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:1089
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:1426
static struct vmbus_driver * vmbus_find_driver(const union uuid *type)
Find driver for VMBus device.
Definition vmbus.c:1123
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:1270
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