iPXE
Data Structures | Macros | Enumerations | Functions | Variables
vmbus.h File Reference

Hyper-V virtual machine bus. More...

#include <byteswap.h>
#include <ipxe/uuid.h>
#include <ipxe/device.h>
#include <ipxe/tables.h>
#include <ipxe/uaccess.h>
#include <ipxe/iobuf.h>
#include <ipxe/hyperv.h>

Go to the source code of this file.

Data Structures

union  vmbus_version
 VMBus version number. More...
 
struct  vmbus_gpa_range
 Guest physical address range descriptor. More...
 
struct  vmbus_message_header
 VMBus message header. More...
 
struct  vmbus_offer_channel
 VMBus "offer channel" message. More...
 
struct  vmbus_open_channel
 VMBus "open channel" message. More...
 
struct  vmbus_open_channel_result
 VMBus "open channel result" message. More...
 
struct  vmbus_close_channel
 VMBus "close channel" message. More...
 
struct  vmbus_gpadl_header
 VMBus "GPADL header" message. More...
 
struct  vmbus_gpadl_created
 VMBus "GPADL created" message. More...
 
struct  vmbus_gpadl_teardown
 VMBus "GPADL teardown" message. More...
 
struct  vmbus_gpadl_torndown
 VMBus "GPADL torndown" message. More...
 
struct  vmbus_initiate_contact
 VMBus "initiate contact" message. More...
 
struct  vmbus_version_response
 VMBus "version response" message. More...
 
union  vmbus_message
 VMBus message. More...
 
struct  vmbus_packet_header
 VMBus packet header. More...
 
struct  vmbus_gpa_direct_header
 VMBus GPA direct header. More...
 
struct  vmbus_xfer_page_range
 VMBus transfer page range. More...
 
struct  vmbus_xfer_page_header
 VMBus transfer page header. More...
 
union  vmbus_packet_header_max
 VMBus maximum-sized packet header. More...
 
struct  vmbus_packet_footer
 VMBus packet footer. More...
 
struct  vmbus_ring
 VMBus ring buffer. More...
 
struct  vmbus_interrupt
 VMBus interrupt page. More...
 
struct  vmbus
 A virtual machine bus. More...
 
struct  vmbus_channel_operations
 VMBus channel operations. More...
 
struct  vmbus_xfer_pages_operations
 VMBus transfer page set operations. More...
 
struct  vmbus_xfer_pages
 VMBus transfer page set. More...
 
struct  vmbus_device
 A VMBus device. More...
 
struct  vmbus_driver
 A VMBus device driver. More...
 

Macros

#define VMBUS_MESSAGE_ID   1
 VMBus message connection ID. More...
 
#define VMBUS_EVENT_ID   2
 VMBus event connection ID. More...
 
#define VMBUS_MESSAGE_TYPE   1
 VMBus message type. More...
 
#define VMBUS_MESSAGE_SINT   2
 VMBus message synthetic interrupt. More...
 
#define VMBUS_PACKET_MAX_HEADER_LEN   64
 Maximum expected size of VMBus packet header. More...
 
#define VMBUS_DRIVERS   __table ( struct vmbus_driver, "vmbus_drivers" )
 VMBus device driver table. More...
 
#define __vmbus_driver   __table_entry ( VMBUS_DRIVERS, 01 )
 Declare a VMBus device driver. More...
 
#define VMBUS_TYPE(a, b, c, d, e0, e1, e2, e3, e4, e5)
 Construct VMBus type. More...
 

Enumerations

enum  vmbus_raw_version { VMBUS_VERSION_WS2008 = ( ( 0 << 16 ) | ( 13 << 0 ) ), VMBUS_VERSION_WIN7 = ( ( 1 << 16 ) | ( 1 << 0 ) ), VMBUS_VERSION_WIN8 = ( ( 2 << 16 ) | ( 4 << 0 ) ), VMBUS_VERSION_WIN8_1 = ( ( 3 << 16 ) | ( 0 << 0 ) ) }
 Known VMBus protocol versions. More...
 
enum  vmbus_message_type {
  VMBUS_OFFER_CHANNEL = 1, VMBUS_REQUEST_OFFERS = 3, VMBUS_ALL_OFFERS_DELIVERED = 4, VMBUS_OPEN_CHANNEL = 5,
  VMBUS_OPEN_CHANNEL_RESULT = 6, VMBUS_CLOSE_CHANNEL = 7, VMBUS_GPADL_HEADER = 8, VMBUS_GPADL_CREATED = 10,
  VMBUS_GPADL_TEARDOWN = 11, VMBUS_GPADL_TORNDOWN = 12, VMBUS_INITIATE_CONTACT = 14, VMBUS_VERSION_RESPONSE = 15,
  VMBUS_UNLOAD = 16, VMBUS_UNLOAD_RESPONSE = 17
}
 VMBus message types. More...
 
enum  vmbus_packet_type {
  VMBUS_DATA_INBAND = 6, VMBUS_DATA_XFER_PAGES = 7, VMBUS_DATA_GPA_DIRECT = 9, VMBUS_CANCELLATION = 10,
  VMBUS_COMPLETION = 11
}
 VMBus packet types. More...
 
enum  vmbus_packet_flags { VMBUS_COMPLETION_REQUESTED = 0x0001 }
 VMBus packet flags. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static void vmbus_set_drvdata (struct vmbus_device *vmdev, void *priv)
 Set VMBus device driver-private data. More...
 
static void * vmbus_get_drvdata (struct vmbus_device *vmdev)
 Get VMBus device driver-private data. More...
 
static int vmbus_has_data (struct vmbus_device *vmdev)
 Check if data is present in ring buffer. More...
 
static int vmbus_register_pages (struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
 Register transfer page set. More...
 
static void vmbus_unregister_pages (struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
 Unregister transfer page set. More...
 
static int vmbus_gpadl_is_obsolete (unsigned int gpadl)
 Check if GPADL is obsolete. More...
 
int vmbus_establish_gpadl (struct vmbus_device *vmdev, userptr_t data, size_t len)
 Establish GPA descriptor list. More...
 
int vmbus_gpadl_teardown (struct vmbus_device *vmdev, unsigned int gpadl)
 Tear down GPA descriptor list. More...
 
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. More...
 
void vmbus_close (struct vmbus_device *vmdev)
 Close VMBus channel. More...
 
int vmbus_send_control (struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
 Send control packet via ring buffer. More...
 
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. More...
 
int vmbus_send_completion (struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
 Send completion packet via ring buffer. More...
 
int vmbus_send_cancellation (struct vmbus_device *vmdev, uint64_t xid)
 Send cancellation packet via ring buffer. More...
 
int vmbus_poll (struct vmbus_device *vmdev)
 Poll ring buffer. More...
 
void vmbus_dump_channel (struct vmbus_device *vmdev)
 Dump channel status (for debugging) More...
 
int vmbus_probe (struct hv_hypervisor *hv, struct device *parent)
 Probe Hyper-V virtual machine bus. More...
 
int vmbus_reset (struct hv_hypervisor *hv, struct device *parent)
 Reset Hyper-V virtual machine bus. More...
 
void vmbus_remove (struct hv_hypervisor *hv, struct device *parent)
 Remove Hyper-V virtual machine bus. More...
 

Variables

unsigned int vmbus_obsolete_gpadl
 Obsolete GPADL ID threshold. More...
 

Detailed Description

Hyper-V virtual machine bus.

Definition in file vmbus.h.

Macro Definition Documentation

◆ VMBUS_MESSAGE_ID

#define VMBUS_MESSAGE_ID   1

VMBus message connection ID.

Definition at line 21 of file vmbus.h.

◆ VMBUS_EVENT_ID

#define VMBUS_EVENT_ID   2

VMBus event connection ID.

Definition at line 24 of file vmbus.h.

◆ VMBUS_MESSAGE_TYPE

#define VMBUS_MESSAGE_TYPE   1

VMBus message type.

Definition at line 27 of file vmbus.h.

◆ VMBUS_MESSAGE_SINT

#define VMBUS_MESSAGE_SINT   2

VMBus message synthetic interrupt.

Definition at line 30 of file vmbus.h.

◆ VMBUS_PACKET_MAX_HEADER_LEN

#define VMBUS_PACKET_MAX_HEADER_LEN   64

Maximum expected size of VMBus packet header.

Definition at line 334 of file vmbus.h.

◆ VMBUS_DRIVERS

#define VMBUS_DRIVERS   __table ( struct vmbus_driver, "vmbus_drivers" )

VMBus device driver table.

Definition at line 546 of file vmbus.h.

◆ __vmbus_driver

#define __vmbus_driver   __table_entry ( VMBUS_DRIVERS, 01 )

Declare a VMBus device driver.

Definition at line 549 of file vmbus.h.

◆ VMBUS_TYPE

#define VMBUS_TYPE (   a,
  b,
  c,
  d,
  e0,
  e1,
  e2,
  e3,
  e4,
  e5 
)
Value:
{ \
.canonical = { \
cpu_to_le32 ( a ), cpu_to_le16 ( b ), \
cpu_to_le16 ( c ), cpu_to_be16 ( d ), \
{ e0, e1, e2, e3, e4, e5 } \
} }
#define cpu_to_be16(value)
Definition: byteswap.h:109
static __always_inline void off_t int c
Definition: librm.h:173
#define cpu_to_le16(value)
Definition: byteswap.h:106

Construct VMBus type.

Definition at line 572 of file vmbus.h.

Enumeration Type Documentation

◆ vmbus_raw_version

Known VMBus protocol versions.

Enumerator
VMBUS_VERSION_WS2008 

Windows Server 2008.

VMBUS_VERSION_WIN7 

Windows 7.

VMBUS_VERSION_WIN8 

Windows 8.

VMBUS_VERSION_WIN8_1 

Windows 8.1.

Definition at line 46 of file vmbus.h.

46  {
47  /** Windows Server 2008 */
48  VMBUS_VERSION_WS2008 = ( ( 0 << 16 ) | ( 13 << 0 ) ),
49  /** Windows 7 */
50  VMBUS_VERSION_WIN7 = ( ( 1 << 16 ) | ( 1 << 0 ) ),
51  /** Windows 8 */
52  VMBUS_VERSION_WIN8 = ( ( 2 << 16 ) | ( 4 << 0 ) ),
53  /** Windows 8.1 */
54  VMBUS_VERSION_WIN8_1 = ( ( 3 << 16 ) | ( 0 << 0 ) ),
55 };
Windows 7.
Definition: vmbus.h:50
Windows 8.1.
Definition: vmbus.h:54
Windows 8.
Definition: vmbus.h:52
Windows Server 2008.
Definition: vmbus.h:48

◆ vmbus_message_type

VMBus message types.

Enumerator
VMBUS_OFFER_CHANNEL 
VMBUS_REQUEST_OFFERS 
VMBUS_ALL_OFFERS_DELIVERED 
VMBUS_OPEN_CHANNEL 
VMBUS_OPEN_CHANNEL_RESULT 
VMBUS_CLOSE_CHANNEL 
VMBUS_GPADL_HEADER 
VMBUS_GPADL_CREATED 
VMBUS_GPADL_TEARDOWN 
VMBUS_GPADL_TORNDOWN 
VMBUS_INITIATE_CONTACT 
VMBUS_VERSION_RESPONSE 
VMBUS_UNLOAD 
VMBUS_UNLOAD_RESPONSE 

Definition at line 80 of file vmbus.h.

◆ vmbus_packet_type

VMBus packet types.

Enumerator
VMBUS_DATA_INBAND 
VMBUS_DATA_XFER_PAGES 
VMBUS_DATA_GPA_DIRECT 
VMBUS_CANCELLATION 
VMBUS_COMPLETION 

Definition at line 284 of file vmbus.h.

◆ vmbus_packet_flags

VMBus packet flags.

Enumerator
VMBUS_COMPLETION_REQUESTED 

Definition at line 293 of file vmbus.h.

293  {
295 };

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ vmbus_set_drvdata()

static void vmbus_set_drvdata ( struct vmbus_device vmdev,
void *  priv 
)
inlinestatic

Set VMBus device driver-private data.

Parameters
vmdevVMBus device
privPrivate data

Definition at line 557 of file vmbus.h.

557  {
558  vmdev->priv = priv;
559 }
void * priv
Driver-private data.
Definition: vmbus.h:517
static struct tlan_private * priv
Definition: tlan.c:224

References priv, and vmbus_device::priv.

Referenced by netvsc_probe().

◆ vmbus_get_drvdata()

static void* vmbus_get_drvdata ( struct vmbus_device vmdev)
inlinestatic

Get VMBus device driver-private data.

Parameters
vmdevVMBus device
Return values
privPrivate data

Definition at line 567 of file vmbus.h.

567  {
568  return vmdev->priv;
569 }
void * priv
Driver-private data.
Definition: vmbus.h:517

References vmbus_device::priv.

Referenced by netvsc_recv_cancellation(), netvsc_recv_completion(), netvsc_recv_control(), netvsc_recv_data(), netvsc_remove(), and netvsc_reset().

◆ vmbus_has_data()

static int vmbus_has_data ( struct vmbus_device vmdev)
inlinestatic

Check if data is present in ring buffer.

Parameters
vmdevVMBus device
has_dataData is present

Definition at line 586 of file vmbus.h.

586  {
587 
588  return ( vmdev->in->prod != vmdev->in->cons );
589 }
uint32_t prod
Producer index (modulo ring length)
Definition: vmbus.h:363
uint32_t cons
Consumer index (modulo ring length)
Definition: vmbus.h:365
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501

References vmbus_ring::cons, vmbus_device::in, and vmbus_ring::prod.

Referenced by netvsc_poll(), and vmbus_poll().

◆ vmbus_register_pages()

static int vmbus_register_pages ( struct vmbus_device vmdev,
struct vmbus_xfer_pages pages 
)
inlinestatic

Register transfer page set.

Parameters
vmdevVMBus device
pagesTransfer page set
Return values
rcReturn status code

Definition at line 599 of file vmbus.h.

600  {
601 
602  list_add ( &pages->list, &vmdev->pages );
603  return 0;
604 }
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
struct list_head list
List of all transfer page sets.
Definition: vmbus.h:468
struct list_head pages
List of transfer page sets.
Definition: vmbus.h:512

References list_add, and vmbus_device::pages.

Referenced by netvsc_create_buffer().

◆ vmbus_unregister_pages()

static void vmbus_unregister_pages ( struct vmbus_device vmdev,
struct vmbus_xfer_pages pages 
)
inlinestatic

Unregister transfer page set.

Parameters
vmdevVMBus device
pagesTransfer page set

Definition at line 613 of file vmbus.h.

614  {
615 
616  list_check_contains_entry ( pages, &vmdev->pages, list );
617  list_del ( &pages->list );
618 }
struct list_head list
List of all transfer page sets.
Definition: vmbus.h:468
struct list_head list
List of network devices.
Definition: netdevice.h:356
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define list_check_contains_entry(entry, head, member)
Check list contains a specified entry.
Definition: list.h:549
struct list_head pages
List of transfer page sets.
Definition: vmbus.h:512

References list_check_contains_entry, list_del, and vmbus_device::pages.

Referenced by netvsc_create_buffer(), and netvsc_destroy_buffer().

◆ vmbus_gpadl_is_obsolete()

static int vmbus_gpadl_is_obsolete ( unsigned int  gpadl)
inlinestatic

Check if GPADL is obsolete.

Parameters
gpadlGPADL ID
is_obsoleteGPADL ID is obsolete

Check if GPADL is obsolete (i.e. was created before the most recent Hyper-V reset).

Definition at line 632 of file vmbus.h.

632  {
633 
634  return ( gpadl <= vmbus_obsolete_gpadl );
635 }
unsigned int vmbus_obsolete_gpadl
Obsolete GPADL ID threshold.
Definition: vmbus.c:61
uint32_t gpadl
GPADL ID.
Definition: netvsc.h:14

References gpadl, and vmbus_obsolete_gpadl.

Referenced by vmbus_gpadl_teardown().

◆ vmbus_establish_gpadl()

int vmbus_establish_gpadl ( struct vmbus_device vmdev,
userptr_t  data,
size_t  len 
)

Establish GPA descriptor list.

Parameters
vmdevVMBus device
dataData buffer
lenLength of data buffer
Return values
gpadlGPADL ID, or negative error

Definition at line 276 of file vmbus.c.

277  {
278  struct hv_hypervisor *hv = vmdev->hv;
279  struct vmbus *vmbus = hv->vmbus;
280  physaddr_t addr = user_to_phys ( data, 0 );
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 }
#define __attribute__(x)
Definition: compiler.h:10
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define le32_to_cpu(value)
Definition: byteswap.h:113
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
unsigned long long uint64_t
Definition: stdint.h:13
#define PAGE_SIZE
Page size.
Definition: io.h:27
uint32_t status
Creation status.
Definition: vmbus.h:190
VMBus "GPADL created" message.
Definition: vmbus.h:182
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
Guest physical address range descriptor.
Definition: vmbus.h:58
uint32_t gpadl
GPADL ID.
Definition: vmbus.h:188
uint32_t channel
Channel ID.
Definition: vmbus.h:186
static int vmbus_post_message(struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
Post message.
Definition: vmbus.c:71
static unsigned int vmbus_gpadl
Current (i.e.
Definition: vmbus.c:54
A virtual machine bus.
Definition: vmbus.h:383
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define EPROTO
Protocol error.
Definition: errno.h:624
struct vmbus_gpadl_created created
"GPADL created" message
Definition: vmbus.h:254
static __always_inline void struct pci_range * range
Definition: pcidirect.h:46
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
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
uint32_t gpadl
GPADL ID.
Definition: netvsc.h:14
unsigned long physaddr_t
Definition: stdint.h:20
A Hyper-V hypervisor.
Definition: hyperv.h:203
unsigned int channel
Channel ID.
Definition: vmbus.h:485
uint64_t pfn[0]
Page frame numbers.
Definition: vmbus.h:68
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
u32 addr
Definition: sky2.h:8
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
uint32_t len
Length.
Definition: ena.h:14
VMBus "GPADL header" message.
Definition: vmbus.h:166
void * memset(void *dest, int character, size_t len) __nonnull

References __attribute__, addr, vmbus_gpadl_created::channel, vmbus_device::channel, cpu_to_le16, cpu_to_le32, vmbus_message::created, data, DBGC, vmbus_device::dev, EPROTO, gpadl, vmbus_gpadl_created::gpadl, vmbus_device::hv, hv_pfn_count(), le32_to_cpu, len, memset(), vmbus::message, device::name, PAGE_SIZE, vmbus_gpa_range::pfn, range, rc, vmbus_gpadl_created::status, user_to_phys(), hv_hypervisor::vmbus, vmbus_gpadl, VMBUS_GPADL_CREATED, VMBUS_GPADL_HEADER, vmbus_post_message(), and vmbus_wait_for_message().

Referenced by netvsc_create_buffer(), and vmbus_open().

◆ vmbus_gpadl_teardown()

int vmbus_gpadl_teardown ( struct vmbus_device vmdev,
unsigned int  gpadl 
)

Tear down GPA descriptor list.

Parameters
vmdevVMBus device
gpadlGPADL ID
Return values
rcReturn status code

Definition at line 347 of file vmbus.c.

347  {
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  */
360  if ( vmbus_gpadl_is_obsolete ( gpadl ) )
361  return 0;
362 
363  /* Construct message */
364  memset ( &teardown, 0, sizeof ( teardown ) );
365  teardown.header.type = cpu_to_le32 ( VMBUS_GPADL_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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define le32_to_cpu(value)
Definition: byteswap.h:113
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
uint32_t gpadl
GPADL ID.
Definition: vmbus.h:208
struct vmbus_gpadl_torndown torndown
"GPADL torndown" message
Definition: vmbus.h:258
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
static int vmbus_gpadl_is_obsolete(unsigned int gpadl)
Check if GPADL is obsolete.
Definition: vmbus.h:632
static int vmbus_post_message(struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
Post message.
Definition: vmbus.c:71
A virtual machine bus.
Definition: vmbus.h:383
VMBus "GPADL torndown" message.
Definition: vmbus.h:204
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define EPROTO
Protocol error.
Definition: errno.h:624
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
uint32_t gpadl
GPADL ID.
Definition: netvsc.h:14
A Hyper-V hypervisor.
Definition: hyperv.h:203
unsigned int channel
Channel ID.
Definition: vmbus.h:485
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
VMBus "GPADL teardown" message.
Definition: vmbus.h:194
void * memset(void *dest, int character, size_t len) __nonnull

References vmbus_gpadl_teardown::channel, vmbus_device::channel, cpu_to_le32, DBGC, vmbus_device::dev, EPROTO, gpadl, vmbus_gpadl_teardown::gpadl, vmbus_gpadl_torndown::gpadl, vmbus_gpadl_teardown::header, vmbus_device::hv, le32_to_cpu, memset(), vmbus::message, device::name, rc, vmbus_message::torndown, vmbus_message_header::type, hv_hypervisor::vmbus, vmbus_gpadl_is_obsolete(), VMBUS_GPADL_TEARDOWN, VMBUS_GPADL_TORNDOWN, vmbus_post_message(), and vmbus_wait_for_message().

Referenced by netvsc_create_buffer(), and vmbus_open().

◆ vmbus_open()

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.

Parameters
vmdevVMBus device
opChannel operations
out_lenOutbound ring buffer length
in_lenInbound ring buffer length
mtuMaximum expected data packet length (including headers)
Return values
rcReturn status code

Both outbound and inbound ring buffer lengths must be a power of two and a multiple of PAGE_SIZE. The requirement to be a power of two is a policy decision taken to simplify the ring buffer indexing logic.

Definition at line 403 of file vmbus.c.

405  {
406  struct hv_hypervisor *hv = vmdev->hv;
407  struct vmbus *vmbus = hv->vmbus;
408  struct vmbus_open_channel open;
409  const struct vmbus_open_channel_result *opened =
410  &vmbus->message->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, virt_to_user ( 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,
468  VMBUS_OPEN_CHANNEL_RESULT ) ) != 0)
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 }
uint32_t channel
Channel ID.
Definition: vmbus.h:150
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct vmbus_ring * out
Outbound ring buffer.
Definition: vmbus.h:499
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define le32_to_cpu(value)
Definition: byteswap.h:113
struct vmbus_channel_operations * op
Channel operations.
Definition: vmbus.h:506
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
uint32_t status
Status.
Definition: vmbus.h:154
static void *__malloc malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition: malloc.h:62
uint32_t out_len
Outbound ring buffer length.
Definition: vmbus.h:495
#define PAGE_SIZE
Page size.
Definition: io.h:27
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
VMBus "open channel" message.
Definition: vmbus.h:128
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
VMBus packet header.
Definition: vmbus.h:266
uint32_t in_len
Inbound ring buffer length.
Definition: vmbus.h:497
void * packet
Packet buffer.
Definition: vmbus.h:510
static int vmbus_post_message(struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
Post message.
Definition: vmbus.c:71
A virtual machine bus.
Definition: vmbus.h:383
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define EPROTO
Protocol error.
Definition: errno.h:624
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:31
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
uint32_t gpadl
GPADL ID.
Definition: netvsc.h:14
int vmbus_gpadl_teardown(struct vmbus_device *vmdev, unsigned int gpadl)
Tear down GPA descriptor list.
Definition: vmbus.c:347
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501
unsigned int uint32_t
Definition: stdint.h:12
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
uint32_t id
Open ID.
Definition: vmbus.h:152
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
A Hyper-V hypervisor.
Definition: hyperv.h:203
VMBus "open channel result" message.
Definition: vmbus.h:146
unsigned int channel
Channel ID.
Definition: vmbus.h:485
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
uint32_t mtu
Maximum MTU.
Definition: ena.h:28
unsigned int gpadl
Ring buffer GPADL ID.
Definition: vmbus.h:503
struct vmbus_open_channel_result opened
"Open channel result" message
Definition: vmbus.h:248
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
int open(const char *uri_string)
Open file.
Definition: posix_io.c:176
static void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Definition: malloc.h:77
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
int vmbus_establish_gpadl(struct vmbus_device *vmdev, userptr_t data, size_t len)
Establish GPA descriptor list.
Definition: vmbus.c:276
size_t mtu
Maximum expected data packet length.
Definition: vmbus.h:508
uint32_t len
Length.
Definition: ena.h:14
void * memset(void *dest, int character, size_t len) __nonnull

References assert(), vmbus_open_channel_result::channel, vmbus_device::channel, cpu_to_le32, DBGC, vmbus_device::dev, ENOMEM, EPROTO, free, free_phys(), gpadl, vmbus_device::gpadl, vmbus_device::hv, vmbus_open_channel_result::id, vmbus_device::in, vmbus_device::in_len, le32_to_cpu, len, malloc(), malloc_phys(), memset(), vmbus::message, mtu, vmbus_device::mtu, device::name, op, vmbus_device::op, open(), vmbus_message::opened, vmbus_device::out, vmbus_device::out_len, vmbus_device::packet, PAGE_SIZE, random(), rc, vmbus_open_channel_result::status, virt_to_phys(), virt_to_user(), hv_hypervisor::vmbus, vmbus_establish_gpadl(), vmbus_gpadl_teardown(), VMBUS_OPEN_CHANNEL, VMBUS_OPEN_CHANNEL_RESULT, vmbus_post_message(), and vmbus_wait_for_message().

Referenced by netvsc_open().

◆ vmbus_close()

void vmbus_close ( struct vmbus_device vmdev)

Close VMBus channel.

Parameters
vmdevVMBus device

Definition at line 524 of file vmbus.c.

524  {
525  struct hv_hypervisor *hv = vmdev->hv;
526  struct vmbus_close_channel close;
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct vmbus_ring * out
Outbound ring buffer.
Definition: vmbus.h:499
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
uint32_t out_len
Outbound ring buffer length.
Definition: vmbus.h:495
uint32_t in_len
Inbound ring buffer length.
Definition: vmbus.h:497
void * packet
Packet buffer.
Definition: vmbus.h:510
static int vmbus_post_message(struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
Post message.
Definition: vmbus.c:71
#define cpu_to_le32(value)
Definition: byteswap.h:107
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501
A Hyper-V hypervisor.
Definition: hyperv.h:203
unsigned int channel
Channel ID.
Definition: vmbus.h:485
VMBus "close channel" message.
Definition: vmbus.h:158
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
unsigned int gpadl
Ring buffer GPADL ID.
Definition: vmbus.h:503
static void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Definition: malloc.h:77
VMBus "GPADL teardown" message.
Definition: vmbus.h:194
static struct evtchn_close * close
Definition: xenevent.h:23
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
void * memset(void *dest, int character, size_t len) __nonnull

References vmbus_device::channel, close, cpu_to_le32, DBGC, vmbus_device::dev, free, free_phys(), vmbus_device::gpadl, vmbus_device::hv, vmbus_device::in, vmbus_device::in_len, len, memset(), device::name, NULL, vmbus_device::out, vmbus_device::out_len, vmbus_device::packet, rc, strerror(), VMBUS_CLOSE_CHANNEL, and vmbus_post_message().

Referenced by netvsc_close(), and netvsc_open().

◆ vmbus_send_control()

int vmbus_send_control ( struct vmbus_device vmdev,
uint64_t  xid,
const void *  data,
size_t  len 
)

Send control packet via ring buffer.

Parameters
vmdevVMBus device
xidTransaction ID (or zero to not request completion)
dataData
lenLength of data
Return values
rcReturn status code

Send data using a VMBUS_DATA_INBAND packet.

Definition at line 765 of file vmbus.c.

766  {
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 }
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
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
VMBus packet header.
Definition: vmbus.h:266
void * packet
Packet buffer.
Definition: vmbus.h:510
uint8_t flags
Flags.
Definition: ena.h:92
uint64_t xid
Transaction ID.
Definition: vmbus.h:280
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References assert(), cpu_to_le16, data, ena_aq_header::flags, header, len, NULL, vmbus_device::packet, VMBUS_COMPLETION_REQUESTED, VMBUS_DATA_INBAND, vmbus_send(), and vmbus_packet_header::xid.

Referenced by netvsc_control().

◆ vmbus_send_data()

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.

Parameters
vmdevVMBus device
xidTransaction ID
dataData
lenLength of data
iobufI/O buffer
Return values
rcReturn status code

Send data using a VMBUS_DATA_GPA_DIRECT packet. The caller is responsible for ensuring that the I/O buffer remains untouched until the corresponding completion has been received.

Definition at line 794 of file vmbus.c.

795  {
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 );
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 }
#define __attribute__(x)
Definition: compiler.h:10
unsigned long long uint64_t
Definition: stdint.h:13
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
#define PAGE_SIZE
Page size.
Definition: io.h:27
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
Guest physical address range descriptor.
Definition: vmbus.h:58
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
void * packet
Packet buffer.
Definition: vmbus.h:510
uint8_t flags
Flags.
Definition: ena.h:92
#define cpu_to_le32(value)
Definition: byteswap.h:107
static __always_inline void struct pci_range * range
Definition: pcidirect.h:46
VMBus GPA direct header.
Definition: vmbus.h:298
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
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
unsigned long physaddr_t
Definition: stdint.h:20
uint64_t pfn[0]
Page frame numbers.
Definition: vmbus.h:68
void * data
Start of data.
Definition: iobuf.h:48
u32 addr
Definition: sky2.h:8
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
size_t mtu
Maximum expected data packet length.
Definition: vmbus.h:508
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References __attribute__, addr, assert(), cpu_to_le16, cpu_to_le32, data, io_buffer::data, ena_aq_header::flags, header, hv_pfn_count(), iob_len(), len, vmbus_device::mtu, NULL, vmbus_device::packet, PAGE_SIZE, vmbus_gpa_range::pfn, range, virt_to_phys(), VMBUS_COMPLETION_REQUESTED, VMBUS_DATA_GPA_DIRECT, and vmbus_send().

Referenced by netvsc_transmit().

◆ vmbus_send_completion()

int vmbus_send_completion ( struct vmbus_device vmdev,
uint64_t  xid,
const void *  data,
size_t  len 
)

Send completion packet via ring buffer.

Parameters
vmdevVMBus device
xidTransaction ID
dataData
lenLength of data
Return values
rcReturn status code

Send data using a VMBUS_COMPLETION packet.

Definition at line 834 of file vmbus.c.

835  {
836  struct vmbus_packet_header *header = vmdev->packet;
837 
838  /* Construct header in packet buffer */
839  assert ( header != NULL );
840  header->type = cpu_to_le16 ( VMBUS_COMPLETION );
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 }
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
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
VMBus packet header.
Definition: vmbus.h:266
void * packet
Packet buffer.
Definition: vmbus.h:510
uint8_t flags
Flags.
Definition: ena.h:92
uint64_t xid
Transaction ID.
Definition: vmbus.h:280
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References assert(), cpu_to_le16, data, ena_aq_header::flags, header, len, NULL, vmbus_device::packet, VMBUS_COMPLETION, vmbus_send(), and vmbus_packet_header::xid.

Referenced by netvsc_recv_data().

◆ vmbus_send_cancellation()

int vmbus_send_cancellation ( struct vmbus_device vmdev,
uint64_t  xid 
)

Send cancellation packet via ring buffer.

Parameters
vmdevVMBus device
xidTransaction ID
Return values
rcReturn status code

Send data using a VMBUS_CANCELLATION packet.

Definition at line 857 of file vmbus.c.

857  {
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 }
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
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
VMBus packet header.
Definition: vmbus.h:266
void * packet
Packet buffer.
Definition: vmbus.h:510
uint8_t flags
Flags.
Definition: ena.h:92
uint64_t xid
Transaction ID.
Definition: vmbus.h:280
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References assert(), cpu_to_le16, ena_aq_header::flags, header, NULL, vmbus_device::packet, VMBUS_CANCELLATION, vmbus_send(), and vmbus_packet_header::xid.

Referenced by netvsc_cancel_transmit().

◆ vmbus_poll()

int vmbus_poll ( struct vmbus_device vmdev)

Poll ring buffer.

Parameters
vmdevVMBus device
Return values
rcReturn status code

Definition at line 972 of file vmbus.c.

972  {
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 
1039  case cpu_to_le16 ( VMBUS_DATA_INBAND ) :
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 
1067  case cpu_to_le16 ( VMBUS_CANCELLATION ) :
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 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
static int vmbus_has_data(struct vmbus_device *vmdev)
Check if data is present in ring buffer.
Definition: vmbus.h:586
#define le32_to_cpu(value)
Definition: byteswap.h:113
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
unsigned long long uint64_t
Definition: stdint.h:13
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
A doubly-linked list entry (or list head)
Definition: list.h:18
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
#define rmb()
Definition: io.h:484
uint32_t cons
Consumer index (modulo ring length)
Definition: vmbus.h:365
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
VMBus packet header.
Definition: vmbus.h:266
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
uint32_t in_len
Inbound ring buffer length.
Definition: vmbus.h:497
void * packet
Packet buffer.
Definition: vmbus.h:510
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define DBGC2_HDA(...)
Definition: compiler.h:523
#define ERANGE
Result too large.
Definition: errno.h:639
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
uint16_t cons
Consumer index.
Definition: ena.h:22
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501
#define le16_to_cpu(value)
Definition: byteswap.h:112
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
#define DBGC2(...)
Definition: compiler.h:522
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define le64_to_cpu(value)
Definition: byteswap.h:114
size_t mtu
Maximum expected data packet length.
Definition: vmbus.h:508
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
if(natsemi->flags &NATSEMI_64BIT) return 1

References assert(), cons, vmbus_ring::cons, cpu_to_le16, cpu_to_le32, data, DBGC, DBGC2, DBGC2_HDA, vmbus_device::dev, EINVAL, ENOTSUP, ERANGE, header, vmbus_device::in, vmbus_device::in_len, INIT_LIST_HEAD, le16_to_cpu, le32_to_cpu, le64_to_cpu, len, vmbus_device::mtu, device::name, NULL, vmbus_device::op, vmbus_device::packet, rc, vmbus_channel_operations::recv_cancellation, vmbus_channel_operations::recv_completion, vmbus_channel_operations::recv_control, vmbus_channel_operations::recv_data, rmb, strerror(), VMBUS_CANCELLATION, VMBUS_COMPLETION, vmbus_consume(), VMBUS_DATA_INBAND, VMBUS_DATA_XFER_PAGES, vmbus_has_data(), and vmbus_xfer_page_iobufs().

Referenced by netvsc_control(), and netvsc_poll().

◆ vmbus_dump_channel()

void vmbus_dump_channel ( struct vmbus_device vmdev)

Dump channel status (for debugging)

Parameters
vmdevVMBus device

Definition at line 1089 of file vmbus.c.

1089  {
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 }
struct vmbus_ring * out
Outbound ring buffer.
Definition: vmbus.h:499
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define le32_to_cpu(value)
Definition: byteswap.h:113
uint32_t first
First block in range.
Definition: pccrr.h:14
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
uint32_t prod
Producer index (modulo ring length)
Definition: vmbus.h:363
uint32_t cons
Consumer index (modulo ring length)
Definition: vmbus.h:365
uint32_t intr_mask
Interrupt mask.
Definition: vmbus.h:367
#define DBGC_HDA(...)
Definition: compiler.h:506
uint32_t in_len
Inbound ring buffer length.
Definition: vmbus.h:497
uint8_t data[0]
Ring buffer contents.
Definition: vmbus.h:371
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501
static __always_inline int off_t userptr_t second
Definition: librm.h:166

References vmbus_ring::cons, vmbus_ring::data, DBGC, DBGC_HDA, vmbus_device::dev, first, vmbus_device::in, vmbus_device::in_len, vmbus_ring::intr_mask, le32_to_cpu, device::name, vmbus_device::out, vmbus_ring::prod, and second.

Referenced by netvsc_control().

◆ vmbus_probe()

int vmbus_probe ( struct hv_hypervisor hv,
struct device parent 
)

Probe Hyper-V virtual machine bus.

Parameters
hvHyper-V hypervisor
parentParent device
Return values
rcReturn status code

Definition at line 1365 of file vmbus.c.

1365  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint8_t data[240]
Message.
Definition: hyperv.h:112
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
struct hv_message received
Received message.
Definition: hyperv.h:197
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
int hv_alloc_pages(struct hv_hypervisor *hv,...)
Allocate zeroed pages.
Definition: hyperv.c:78
A virtual machine bus.
Definition: vmbus.h:383
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
Definition: hyperv.c:113
struct hv_monitor * monitor_in
Inbound notifications.
Definition: vmbus.h:387
static int vmbus_unload(struct hv_hypervisor *hv)
Terminate contact.
Definition: vmbus.c:211
union hv_message_buffer * message
Message buffer.
Definition: hyperv.h:209
static int vmbus_negotiate_version(struct hv_hypervisor *hv)
Negotiate protocol version.
Definition: vmbus.c:231
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
Definition: hyperv.c:423
#define VMBUS_MESSAGE_SINT
VMBus message synthetic interrupt.
Definition: vmbus.h:30
static int vmbus_probe_channels(struct hv_hypervisor *hv, struct device *parent)
Probe channels.
Definition: vmbus.c:1140
struct vmbus_interrupt * intr
Interrupt page.
Definition: vmbus.h:385
struct hv_monitor * monitor_out
Outbound notifications.
Definition: vmbus.h:389
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
Definition: hyperv.c:397
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
static void vmbus_remove_channels(struct hv_hypervisor *hv __unused, struct device *parent)
Remove channels.
Definition: vmbus.c:1339
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References assert(), hv_message::data, ENOMEM, free, hv_alloc_pages(), hv_disable_sint(), hv_enable_sint(), hv_free_pages(), vmbus::intr, hv_hypervisor::message, vmbus::message, vmbus::monitor_in, vmbus::monitor_out, NULL, rc, hv_message_buffer::received, hv_hypervisor::vmbus, VMBUS_MESSAGE_SINT, vmbus_negotiate_version(), vmbus_probe_channels(), vmbus_remove_channels(), vmbus_unload(), and zalloc().

Referenced by hv_probe().

◆ vmbus_reset()

int vmbus_reset ( struct hv_hypervisor hv,
struct device parent 
)

Reset Hyper-V virtual machine bus.

Parameters
hvHyper-V hypervisor
parentParent device
Return values
rcReturn status code

Definition at line 1426 of file vmbus.c.

1426  {
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 );
1435  memset ( vmbus->monitor_in, 0, PAGE_SIZE );
1436  memset ( vmbus->monitor_out, 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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int vmbus_reset_channels(struct hv_hypervisor *hv, struct device *parent)
Reset channels.
Definition: vmbus.c:1270
#define PAGE_SIZE
Page size.
Definition: io.h:27
static unsigned int vmbus_gpadl
Current (i.e.
Definition: vmbus.c:54
A virtual machine bus.
Definition: vmbus.h:383
struct hv_monitor * monitor_in
Inbound notifications.
Definition: vmbus.h:387
static int vmbus_negotiate_version(struct hv_hypervisor *hv)
Negotiate protocol version.
Definition: vmbus.c:231
#define VMBUS_MESSAGE_SINT
VMBus message synthetic interrupt.
Definition: vmbus.h:30
struct vmbus_interrupt * intr
Interrupt page.
Definition: vmbus.h:385
struct hv_monitor * monitor_out
Outbound notifications.
Definition: vmbus.h:389
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
Definition: hyperv.c:397
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
unsigned int vmbus_obsolete_gpadl
Obsolete GPADL ID threshold.
Definition: vmbus.c:61
void * memset(void *dest, int character, size_t len) __nonnull

References hv_enable_sint(), vmbus::intr, memset(), vmbus::monitor_in, vmbus::monitor_out, PAGE_SIZE, rc, hv_hypervisor::vmbus, vmbus_gpadl, VMBUS_MESSAGE_SINT, vmbus_negotiate_version(), vmbus_obsolete_gpadl, and vmbus_reset_channels().

Referenced by hv_unquiesce().

◆ vmbus_remove()

void vmbus_remove ( struct hv_hypervisor hv,
struct device parent 
)

Remove Hyper-V virtual machine bus.

Parameters
hvHyper-V hypervisor
parentParent device

Definition at line 1458 of file vmbus.c.

1458  {
1459  struct vmbus *vmbus = hv->vmbus;
1460 
1461  vmbus_remove_channels ( hv, parent );
1462  vmbus_unload ( hv );
1465  NULL );
1466  free ( vmbus );
1467 }
A virtual machine bus.
Definition: vmbus.h:383
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
Definition: hyperv.c:113
struct hv_monitor * monitor_in
Inbound notifications.
Definition: vmbus.h:387
static int vmbus_unload(struct hv_hypervisor *hv)
Terminate contact.
Definition: vmbus.c:211
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
Definition: hyperv.c:423
#define VMBUS_MESSAGE_SINT
VMBus message synthetic interrupt.
Definition: vmbus.h:30
struct vmbus_interrupt * intr
Interrupt page.
Definition: vmbus.h:385
struct hv_monitor * monitor_out
Outbound notifications.
Definition: vmbus.h:389
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
static void vmbus_remove_channels(struct hv_hypervisor *hv __unused, struct device *parent)
Remove channels.
Definition: vmbus.c:1339
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References free, hv_disable_sint(), hv_free_pages(), vmbus::intr, vmbus::monitor_in, vmbus::monitor_out, NULL, hv_hypervisor::vmbus, VMBUS_MESSAGE_SINT, vmbus_remove_channels(), and vmbus_unload().

Referenced by hv_probe(), and hv_remove().

Variable Documentation

◆ vmbus_obsolete_gpadl

unsigned int vmbus_obsolete_gpadl

Obsolete GPADL ID threshold.

When the Hyper-V connection is reset, any previous GPADLs are automatically rendered obsolete.

Definition at line 61 of file vmbus.c.

Referenced by vmbus_gpadl_is_obsolete(), and vmbus_reset().