iPXE
Macros | Functions | Variables
vmbus.c File Reference

Hyper-V virtual machine bus. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/nap.h>
#include <ipxe/malloc.h>
#include <ipxe/iobuf.h>
#include <ipxe/bitops.h>
#include <ipxe/hyperv.h>
#include <ipxe/vmbus.h>

Go to the source code of this file.

Macros

#define VMBUS_GPADL_MAGIC   0x18ae0000
 VMBus initial GPADL ID. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static int vmbus_post_message (struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
 Post message. More...
 
static int vmbus_post_empty_message (struct hv_hypervisor *hv, unsigned int type)
 Post empty message. More...
 
static int vmbus_wait_for_any_message (struct hv_hypervisor *hv)
 Wait for received message of any type. More...
 
static int vmbus_wait_for_message (struct hv_hypervisor *hv, unsigned int type)
 Wait for received message of a specified type, ignoring any others. More...
 
static int vmbus_initiate_contact (struct hv_hypervisor *hv, unsigned int raw)
 Initiate contact. More...
 
static int vmbus_unload (struct hv_hypervisor *hv)
 Terminate contact. More...
 
static int vmbus_negotiate_version (struct hv_hypervisor *hv)
 Negotiate protocol version. 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...
 
static void vmbus_signal_monitor (struct vmbus_device *vmdev)
 Signal channel via monitor page. More...
 
static void vmbus_signal_event (struct vmbus_device *vmdev)
 Signal channel via hypervisor event. More...
 
static size_t vmbus_produce (struct vmbus_device *vmdev, size_t prod, const void *data, size_t len)
 Fill outbound ring buffer. More...
 
static size_t vmbus_consume (struct vmbus_device *vmdev, size_t cons, void *data, size_t len)
 Consume inbound ring buffer. More...
 
static int vmbus_send (struct vmbus_device *vmdev, struct vmbus_packet_header *header, const void *data, size_t len)
 Send packet via ring buffer. 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...
 
static struct vmbus_xfer_pagesvmbus_xfer_pages (struct vmbus_device *vmdev, uint16_t pageset)
 Get transfer page set from pageset ID. More...
 
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. 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...
 
static struct vmbus_drivervmbus_find_driver (const union uuid *type)
 Find driver for VMBus device. More...
 
static int vmbus_probe_channels (struct hv_hypervisor *hv, struct device *parent)
 Probe channels. More...
 
static int vmbus_reset_channels (struct hv_hypervisor *hv, struct device *parent)
 Reset channels. More...
 
static void vmbus_remove_channels (struct hv_hypervisor *hv __unused, struct device *parent)
 Remove channels. 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

static unsigned int vmbus_gpadl = VMBUS_GPADL_MAGIC
 Current (i.e. More...
 
unsigned int vmbus_obsolete_gpadl
 Obsolete GPADL ID threshold. More...
 

Detailed Description

Hyper-V virtual machine bus.

Definition in file vmbus.c.

Macro Definition Documentation

◆ VMBUS_GPADL_MAGIC

#define VMBUS_GPADL_MAGIC   0x18ae0000

VMBus initial GPADL ID.

This is an opaque value with no meaning. The Linux kernel uses 0xe1e10.

Definition at line 51 of file vmbus.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ vmbus_post_message()

static int vmbus_post_message ( struct hv_hypervisor hv,
const struct vmbus_message_header header,
size_t  len 
)
static

Post message.

Parameters
hvHyper-V hypervisor
headerMessage header
lenLength of message (including header)
Return values
rcReturn status code

Definition at line 71 of file vmbus.c.

73  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define VMBUS_MESSAGE_TYPE
VMBus message type.
Definition: vmbus.h:27
#define DBGC(...)
Definition: compiler.h:505
A virtual machine bus.
Definition: vmbus.h:383
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
A posted message.
Definition: hyperv.h:81
uint32_t len
Length.
Definition: ena.h:14
struct ena_aq_header header
Header.
Definition: ena.h:12
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
#define VMBUS_MESSAGE_ID
VMBus message connection ID.
Definition: vmbus.h:21

References DBGC, header, len, rc, strerror(), hv_hypervisor::vmbus, VMBUS_MESSAGE_ID, and VMBUS_MESSAGE_TYPE.

Referenced by vmbus_close(), vmbus_establish_gpadl(), vmbus_gpadl_teardown(), vmbus_initiate_contact(), vmbus_open(), and vmbus_post_empty_message().

◆ vmbus_post_empty_message()

static int vmbus_post_empty_message ( struct hv_hypervisor hv,
unsigned int  type 
)
static

Post empty message.

Parameters
hvHyper-V hypervisor
typeMessage type
Return values
rcReturn status code

Definition at line 95 of file vmbus.c.

96  {
97  struct vmbus_message_header header = { .type = cpu_to_le32 ( type ) };
98 
99  return vmbus_post_message ( hv, &header, sizeof ( header ) );
100 }
VMBus message header.
Definition: vmbus.h:72
uint8_t type
Type.
Definition: ena.h:16
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
struct ena_aq_header header
Header.
Definition: ena.h:12

References cpu_to_le32, header, type, and vmbus_post_message().

Referenced by vmbus_probe_channels(), vmbus_reset_channels(), and vmbus_unload().

◆ vmbus_wait_for_any_message()

static int vmbus_wait_for_any_message ( struct hv_hypervisor hv)
static

Wait for received message of any type.

Parameters
hvHyper-V hypervisor
Return values
rcReturn status code

Definition at line 108 of file vmbus.c.

108  {
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",
122  vmbus, le32_to_cpu ( hv->message->received.type ) );
123  return -EINVAL;
124  }
125 
126  return 0;
127 }
uint32_t type
Type.
Definition: hyperv.h:102
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define le32_to_cpu(value)
Definition: byteswap.h:113
int hv_wait_for_message(struct hv_hypervisor *hv, unsigned int sintx)
Wait for received message.
Definition: hyperv.c:486
#define VMBUS_MESSAGE_TYPE
VMBus message type.
Definition: vmbus.h:27
#define DBGC(...)
Definition: compiler.h:505
struct hv_message received
Received message.
Definition: hyperv.h:197
A virtual machine bus.
Definition: vmbus.h:383
#define cpu_to_le32(value)
Definition: byteswap.h:107
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
union hv_message_buffer * message
Message buffer.
Definition: hyperv.h:209
#define VMBUS_MESSAGE_SINT
VMBus message synthetic interrupt.
Definition: vmbus.h:30
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211

References cpu_to_le32, DBGC, EINVAL, hv_wait_for_message(), le32_to_cpu, hv_hypervisor::message, rc, hv_message_buffer::received, strerror(), hv_message::type, hv_hypervisor::vmbus, VMBUS_MESSAGE_SINT, and VMBUS_MESSAGE_TYPE.

Referenced by vmbus_probe_channels(), vmbus_reset_channels(), and vmbus_wait_for_message().

◆ vmbus_wait_for_message()

static int vmbus_wait_for_message ( struct hv_hypervisor hv,
unsigned int  type 
)
static

Wait for received message of a specified type, ignoring any others.

Parameters
hvHyper-V hypervisor
typeMessage type
Return values
rcReturn status code

Definition at line 136 of file vmbus.c.

137  {
138  struct vmbus *vmbus = hv->vmbus;
139  const struct vmbus_message_header *header = &vmbus->message->header;
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
VMBus message header.
Definition: vmbus.h:72
#define le32_to_cpu(value)
Definition: byteswap.h:113
uint8_t type
Type.
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
A virtual machine bus.
Definition: vmbus.h:383
#define cpu_to_le32(value)
Definition: byteswap.h:107
static int vmbus_wait_for_any_message(struct hv_hypervisor *hv)
Wait for received message of any type.
Definition: vmbus.c:108
struct ena_aq_header header
Header.
Definition: ena.h:12
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
struct vmbus_message_header header
Common message header.
Definition: vmbus.h:242

References cpu_to_le32, DBGC, header, vmbus_message::header, le32_to_cpu, vmbus::message, rc, type, hv_hypervisor::vmbus, and vmbus_wait_for_any_message().

Referenced by vmbus_establish_gpadl(), vmbus_gpadl_teardown(), vmbus_initiate_contact(), vmbus_open(), and vmbus_unload().

◆ vmbus_initiate_contact()

static int vmbus_initiate_contact ( struct hv_hypervisor hv,
unsigned int  raw 
)
static

Initiate contact.

Parameters
hvHyper-V hypervisor
rawVMBus protocol (raw) version
Return values
rcReturn status code

Definition at line 168 of file vmbus.c.

169  {
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 ) );
177  initiate.header.type = cpu_to_le32 ( VMBUS_INITIATE_CONTACT );
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define DBGC(...)
Definition: compiler.h:505
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
VMBus "version response" message.
Definition: vmbus.h:228
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
VMBus "initiate contact" message.
Definition: vmbus.h:212
u32 version
Version number.
Definition: ath9k_hw.c:1983
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
struct hv_monitor * monitor_in
Inbound notifications.
Definition: vmbus.h:387
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
#define le16_to_cpu(value)
Definition: byteswap.h:112
struct vmbus_version_response version
"Version response" message
Definition: vmbus.h:262
struct vmbus_interrupt * intr
Interrupt page.
Definition: vmbus.h:385
__be32 raw[7]
Definition: CIB_PRM.h:28
struct hv_monitor * monitor_out
Outbound notifications.
Definition: vmbus.h:389
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
void * memset(void *dest, int character, size_t len) __nonnull

References cpu_to_le32, DBGC, ENOTSUP, vmbus_initiate_contact::header, vmbus_initiate_contact::intr, vmbus::intr, le16_to_cpu, vmbus_version::major, memset(), vmbus::message, vmbus_version::minor, vmbus_initiate_contact::monitor_in, vmbus::monitor_in, vmbus_initiate_contact::monitor_out, vmbus::monitor_out, raw, vmbus_version::raw, rc, vmbus_message_header::type, vmbus_initiate_contact::version, vmbus_message::version, version, virt_to_phys(), hv_hypervisor::vmbus, VMBUS_INITIATE_CONTACT, vmbus_post_message(), VMBUS_VERSION_RESPONSE, and vmbus_wait_for_message().

◆ vmbus_unload()

static int vmbus_unload ( struct hv_hypervisor hv)
static

Terminate contact.

Parameters
hvHyper-V hypervisor
Return values
rcReturn status code

Definition at line 211 of file vmbus.c.

211  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int vmbus_post_empty_message(struct hv_hypervisor *hv, unsigned int type)
Post empty message.
Definition: vmbus.c:95
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

References rc, vmbus_post_empty_message(), VMBUS_UNLOAD, VMBUS_UNLOAD_RESPONSE, and vmbus_wait_for_message().

Referenced by vmbus_negotiate_version(), vmbus_probe(), and vmbus_remove().

◆ vmbus_negotiate_version()

static int vmbus_negotiate_version ( struct hv_hypervisor hv)
static

Negotiate protocol version.

Parameters
hvHyper-V hypervisor
Return values
rcReturn status code

Definition at line 231 of file vmbus.c.

231  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
VMBus "initiate contact" message.
Definition: vmbus.h:212
Windows 8.1.
Definition: vmbus.h:54
static int vmbus_unload(struct hv_hypervisor *hv)
Terminate contact.
Definition: vmbus.c:211
Windows Server 2008.
Definition: vmbus.h:48

References rc, vmbus_unload(), VMBUS_VERSION_WIN8_1, and VMBUS_VERSION_WS2008.

Referenced by vmbus_probe(), and vmbus_reset().

◆ 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 unsigned int hv_pfn_count(physaddr_t data, size_t len)
Calculate the number of pages covering an address range.
Definition: hyperv.h:223
u32 addr
Definition: sky2.h:8
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
uint32_t len
Length.
Definition: ena.h:14
uint64_t pfn[0]
Page frame numbers.
Definition: vmbus.h:68
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
#define cpu_to_le16(value)
Definition: byteswap.h:106
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
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, 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_dma ( 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_dma ( 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
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:30
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
uint32_t len
Length.
Definition: ena.h:14
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
static void *__malloc malloc_dma(size_t size, size_t phys_align)
Allocate memory for DMA.
Definition: malloc.h:66
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
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
static void free_dma(void *ptr, size_t size)
Free memory allocated with malloc_dma()
Definition: malloc.h:81
size_t mtu
Maximum expected data packet length.
Definition: vmbus.h:508
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_dma(), 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_dma(), 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_dma ( 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
uint32_t len
Length.
Definition: ena.h:14
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
VMBus "GPADL teardown" message.
Definition: vmbus.h:194
static struct evtchn_close * close
Definition: xenevent.h:23
static void free_dma(void *ptr, size_t size)
Free memory allocated with malloc_dma()
Definition: malloc.h:81
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
void * memset(void *dest, int character, size_t len) __nonnull

References vmbus_device::channel, close, cpu_to_le32, DBGC, vmbus_device::dev, free, free_dma(), 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_signal_monitor()

static void vmbus_signal_monitor ( struct vmbus_device vmdev)
static

Signal channel via monitor page.

Parameters
vmdevVMBus device

Definition at line 574 of file vmbus.c.

574  {
575  struct hv_hypervisor *hv = vmdev->hv;
576  struct vmbus *vmbus = hv->vmbus;
577  struct hv_monitor_trigger *trigger;
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 }
static unsigned int unsigned int bit
Definition: bigint.h:196
struct hv_monitor_trigger trigger[4]
Trigger groups.
Definition: hyperv.h:16
A virtual machine bus.
Definition: vmbus.h:383
void set_bit(unsigned int bit, volatile void *bits)
uint8_t group
Group number.
Definition: scsi.h:25
A monitor trigger group.
Definition: hyperv.h:139
A Hyper-V hypervisor.
Definition: hyperv.h:203
unsigned int monitor
Monitor ID.
Definition: vmbus.h:487
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
struct hv_monitor * monitor_out
Outbound notifications.
Definition: vmbus.h:389
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
struct hv_monitor_trigger trigger[4]
Trigger groups.
Definition: hyperv.h:171
uint32_t pending
Pending events.
Definition: hyperv.h:141

References bit, group, vmbus_device::hv, vmbus_device::monitor, vmbus::monitor_out, hv_monitor_trigger::pending, set_bit(), trigger, hv_monitor::trigger, and hv_hypervisor::vmbus.

Referenced by vmbus_probe_channels().

◆ vmbus_signal_event()

static void vmbus_signal_event ( struct vmbus_device vmdev)
static

Signal channel via hypervisor event.

Parameters
vmdevVMBus device

Definition at line 593 of file vmbus.c.

593  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
A signalled event.
Definition: hyperv.h:119
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
A Hyper-V hypervisor.
Definition: hyperv.h:203
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
#define VMBUS_EVENT_ID
VMBus event connection ID.
Definition: vmbus.h:24

References DBGC, vmbus_device::dev, vmbus_device::hv, device::name, rc, strerror(), and VMBUS_EVENT_ID.

Referenced by vmbus_probe_channels().

◆ vmbus_produce()

static size_t vmbus_produce ( struct vmbus_device vmdev,
size_t  prod,
const void *  data,
size_t  len 
)
static

Fill outbound ring buffer.

Parameters
vmdevVMBus device
prodProducer index
dataData
lenLength
Return values
prodNew producer index

The caller must ensure that there is sufficient space in the ring buffer.

Definition at line 617 of file vmbus.c.

618  {
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 }
struct vmbus_ring * out
Outbound ring buffer.
Definition: vmbus.h:499
static __always_inline int off_t userptr_t second
Definition: efi_uaccess.h:80
uint32_t out_len
Outbound ring buffer length.
Definition: vmbus.h:495
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint8_t data[0]
Ring buffer contents.
Definition: vmbus.h:371
uint32_t len
Length.
Definition: ena.h:14
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23

References data, vmbus_ring::data, first, len, memcpy(), vmbus_device::out, vmbus_device::out_len, and second.

Referenced by vmbus_send().

◆ vmbus_consume()

static size_t vmbus_consume ( struct vmbus_device vmdev,
size_t  cons,
void *  data,
size_t  len 
)
static

Consume inbound ring buffer.

Parameters
vmdevVMBus device
consConsumer index
dataData buffer, or NULL
lenLength to consume
Return values
consNew consumer index

Definition at line 645 of file vmbus.c.

646  {
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 }
static __always_inline int off_t userptr_t second
Definition: efi_uaccess.h:80
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint32_t in_len
Inbound ring buffer length.
Definition: vmbus.h:497
uint8_t data[0]
Ring buffer contents.
Definition: vmbus.h:371
uint16_t cons
Consumer index.
Definition: ena.h:22
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501
uint32_t len
Length.
Definition: ena.h:14
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23

References cons, data, vmbus_ring::data, first, vmbus_device::in, vmbus_device::in_len, len, memcpy(), and second.

Referenced by vmbus_poll().

◆ vmbus_send()

static int vmbus_send ( struct vmbus_device vmdev,
struct vmbus_packet_header header,
const void *  data,
size_t  len 
)
static

Send packet via ring buffer.

Parameters
vmdevVMBus device
headerPacket header
dataData
lenLength of data
Return values
rcReturn status code

Send a packet via the outbound ring buffer. All fields in the packet header must be filled in, with the exception of the total packet length.

Definition at line 677 of file vmbus.c.

679  {
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 }
struct vmbus_ring * out
Outbound ring buffer.
Definition: vmbus.h:499
uint8_t out[PAGE_SIZE/2]
Outbound interrupts.
Definition: vmbus.h:379
wmb()
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 out_len
Outbound ring buffer length.
Definition: vmbus.h:495
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
#define rmb()
Definition: io.h:484
uint32_t prod
Producer index (modulo ring length)
Definition: vmbus.h:363
uint32_t cons
Consumer index (modulo ring length)
Definition: vmbus.h:365
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
uint32_t intr_mask
Interrupt mask.
Definition: vmbus.h:367
A virtual machine bus.
Definition: vmbus.h:383
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define DBGC2_HDA(...)
Definition: compiler.h:523
uint16_t cons
Consumer index.
Definition: ena.h:22
unsigned char uint8_t
Definition: stdint.h:10
void set_bit(unsigned int bit, volatile void *bits)
#define le16_to_cpu(value)
Definition: byteswap.h:112
A Hyper-V hypervisor.
Definition: hyperv.h:203
unsigned int channel
Channel ID.
Definition: vmbus.h:485
uint32_t len
Length.
Definition: ena.h:14
#define ENOBUFS
No buffer space available.
Definition: errno.h:498
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
#define DBGC2(...)
Definition: compiler.h:522
struct ena_aq_header header
Header.
Definition: ena.h:12
struct vmbus_interrupt * intr
Interrupt page.
Definition: vmbus.h:385
uint8_t fill
Length pair.
Definition: deflate.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
void mb(void)
Memory barrier.
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
void(* signal)(struct vmbus_device *vmdev)
Signal channel.
Definition: vmbus.h:492
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References assert(), vmbus_device::channel, cons, vmbus_ring::cons, cpu_to_le16, cpu_to_le32, data, DBGC, DBGC2, DBGC2_HDA, vmbus_device::dev, ENOBUFS, fill, header, vmbus_device::hv, vmbus::intr, vmbus_ring::intr_mask, le16_to_cpu, le32_to_cpu, len, mb(), device::name, NULL, vmbus_interrupt::out, vmbus_device::out, vmbus_device::out_len, vmbus_packet_footer::prod, vmbus_ring::prod, vmbus_packet_footer::reserved, rmb, set_bit(), vmbus_device::signal, hv_hypervisor::vmbus, vmbus_produce(), and wmb().

Referenced by vmbus_send_cancellation(), vmbus_send_completion(), vmbus_send_control(), and vmbus_send_data().

◆ 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:80
uint64_t xid
Transaction ID.
Definition: vmbus.h:280
uint32_t len
Length.
Definition: ena.h:14
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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:80
#define cpu_to_le32(value)
Definition: byteswap.h:107
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:151
u32 addr
Definition: sky2.h:8
unsigned long physaddr_t
Definition: stdint.h:20
uint32_t len
Length.
Definition: ena.h:14
uint64_t pfn[0]
Page frame numbers.
Definition: vmbus.h:68
void * data
Start of data.
Definition: iobuf.h:44
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
size_t mtu
Maximum expected data packet length.
Definition: vmbus.h:508
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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, 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:80
uint64_t xid
Transaction ID.
Definition: vmbus.h:280
uint32_t len
Length.
Definition: ena.h:14
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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:80
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:362

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_xfer_pages()

static struct vmbus_xfer_pages* vmbus_xfer_pages ( struct vmbus_device vmdev,
uint16_t  pageset 
)
static

Get transfer page set from pageset ID.

Parameters
vmdevVMBus device
pagesetPage set ID (in protocol byte order)
Return values
pagesPage set, or NULL if not found

Definition at line 877 of file vmbus.c.

878  {
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 }
uint16_t pageset
Page set ID.
Definition: netvsc.h:16
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
struct list_head list
List of all transfer page sets.
Definition: vmbus.h:468
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
uint16_t pageset
Page set ID (in protocol byte order)
Definition: vmbus.h:470
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
#define le16_to_cpu(value)
Definition: byteswap.h:112
VMBus transfer page set.
Definition: vmbus.h:466
struct list_head pages
List of transfer page sets.
Definition: vmbus.h:512
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References DBGC, vmbus_device::dev, le16_to_cpu, vmbus_xfer_pages::list, list_for_each_entry, device::name, NULL, vmbus_device::pages, pageset, and vmbus_xfer_pages::pageset.

Referenced by vmbus_xfer_page_iobufs().

◆ vmbus_xfer_page_iobufs()

static int vmbus_xfer_page_iobufs ( struct vmbus_device vmdev,
struct vmbus_packet_header header,
struct list_head list 
)
static

Construct I/O buffer list from transfer pages.

Parameters
vmdevVMBus device
headerTransfer page header
listI/O buffer list to populate
Return values
rcReturn status code

Definition at line 900 of file vmbus.c.

902  {
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:
958  list_for_each_entry_safe ( iobuf, tmp, list, list ) {
959  list_del ( &iobuf->list );
960  free_iob ( iobuf );
961  }
962  err_pages:
963  return rc;
964 }
VMBus transfer page header.
Definition: vmbus.h:318
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define iob_put(iobuf, len)
Definition: iobuf.h:116
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
#define le32_to_cpu(value)
Definition: byteswap.h:113
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
#define ENOENT
No such file or directory.
Definition: errno.h:514
struct vmbus_xfer_pages_operations * op
Page set operations.
Definition: vmbus.h:472
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
uint16_t pageset
Page set ID.
Definition: vmbus.h:322
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define ENOMEM
Not enough space.
Definition: errno.h:534
uint32_t range_count
Number of range descriptors.
Definition: vmbus.h:328
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#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:447
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
uint8_t * tmp
Definition: entropy.h:156
uint32_t offset
Offset.
Definition: vmbus.h:314
int(* copy)(struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
Copy data from transfer page.
Definition: vmbus.h:461
VMBus transfer page set.
Definition: vmbus.h:466
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:39
uint32_t len
Length.
Definition: ena.h:14
uint32_t len
Length.
Definition: vmbus.h:312
struct ena_aq_header header
Header.
Definition: ena.h:12
#define cpu_to_le16(value)
Definition: byteswap.h:106
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
A persistent I/O buffer.
Definition: iobuf.h:32
struct vmbus_xfer_page_range range[0]
Range descriptors.
Definition: vmbus.h:330

References alloc_iob(), assert(), container_of, vmbus_xfer_pages_operations::copy, cpu_to_le16, DBGC, vmbus_device::dev, ENOENT, ENOMEM, free_iob(), header, iob_put, le32_to_cpu, len, vmbus_xfer_page_range::len, io_buffer::list, list_add, list_del, list_for_each_entry_safe, device::name, offset, vmbus_xfer_page_range::offset, vmbus_xfer_pages::op, vmbus_xfer_page_header::pageset, vmbus_xfer_page_header::range, vmbus_xfer_page_header::range_count, rc, strerror(), tmp, VMBUS_DATA_XFER_PAGES, and vmbus_xfer_pages().

Referenced by vmbus_poll().

◆ 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
uint32_t len
Length.
Definition: ena.h:14
#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
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define le64_to_cpu(value)
Definition: byteswap.h:114
size_t mtu
Maximum expected data packet length.
Definition: vmbus.h:508
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
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
static __always_inline int off_t userptr_t second
Definition: efi_uaccess.h:80
#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
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23

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_find_driver()

static struct vmbus_driver* vmbus_find_driver ( const union uuid type)
static

Find driver for VMBus device.

Parameters
vmdevVMBus device
Return values
driverDriver, or NULL

Definition at line 1123 of file vmbus.c.

1123  {
1124  struct vmbus_driver *vmdrv;
1125 
1126  for_each_table_entry ( vmdrv, VMBUS_DRIVERS ) {
1127  if ( memcmp ( &vmdrv->type, type, sizeof ( *type ) ) == 0 )
1128  return vmdrv;
1129  }
1130  return NULL;
1131 }
uint8_t type
Type.
Definition: ena.h:16
#define VMBUS_DRIVERS
VMBus device driver table.
Definition: vmbus.h:546
union uuid type
Device type.
Definition: vmbus.h:525
A VMBus device driver.
Definition: vmbus.h:521
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References for_each_table_entry, memcmp(), NULL, type, vmbus_driver::type, and VMBUS_DRIVERS.

Referenced by vmbus_probe_channels().

◆ vmbus_probe_channels()

static int vmbus_probe_channels ( struct hv_hypervisor hv,
struct device parent 
)
static

Probe channels.

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

Definition at line 1140 of file vmbus.c.

1141  {
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 */
1154  if ( ( rc = vmbus_post_empty_message ( hv, VMBUS_REQUEST_OFFERS ) ) !=0)
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 }
const char * name
Name.
Definition: vmbus.h:523
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
VMBus message header.
Definition: vmbus.h:72
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
struct vmbus_offer_channel offer
"Offer channel" message
Definition: vmbus.h:244
#define le32_to_cpu(value)
Definition: byteswap.h:113
A universally unique ID.
Definition: uuid.h:15
uint8_t monitor
Monitor ID.
Definition: vmbus.h:118
uint32_t channel
Channel ID.
Definition: vmbus.h:116
uint8_t type
Type.
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
A VMBus device.
Definition: vmbus.h:476
static int vmbus_post_empty_message(struct hv_hypervisor *hv, unsigned int type)
Post empty message.
Definition: vmbus.c:95
struct device * parent
Bus device.
Definition: device.h:85
static void uuid_mangle(union uuid *uuid)
Change UUID endianness.
Definition: uuid.h:43
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
uint32_t channel
RNDIS channel.
Definition: netvsc.h:14
static struct vmbus_driver * vmbus_find_driver(const union uuid *type)
Find driver for VMBus device.
Definition: vmbus.c:1123
A virtual machine bus.
Definition: vmbus.h:383
const char * driver_name
Driver name.
Definition: device.h:77
union uuid type
Channel type.
Definition: vmbus.h:102
#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:447
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define EPROTO
Protocol error.
Definition: errno.h:624
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
struct vmbus_driver * driver
Driver.
Definition: vmbus.h:515
uint8_t * tmp
Definition: entropy.h:156
A VMBus device driver.
Definition: vmbus.h:521
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition: uuid.c:43
uint8_t monitored
Monitor exists.
Definition: vmbus.h:120
#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:475
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
static int vmbus_wait_for_any_message(struct hv_hypervisor *hv)
Wait for received message of any type.
Definition: vmbus.c:108
unsigned int bus_type
Bus type.
Definition: device.h:24
unsigned int channel
Channel ID.
Definition: vmbus.h:485
unsigned int monitor
Monitor ID.
Definition: vmbus.h:487
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
#define DBGC2(...)
Definition: compiler.h:522
VMBus "offer channel" message.
Definition: vmbus.h:98
struct list_head children
Devices attached to this device.
Definition: device.h:83
static void vmbus_signal_event(struct vmbus_device *vmdev)
Signal channel via hypervisor event.
Definition: vmbus.c:593
struct ena_aq_header header
Header.
Definition: ena.h:12
struct device_description desc
Device description.
Definition: device.h:79
union uuid instance
Channel instance.
Definition: vmbus.h:104
union uuid instance
Channel instance.
Definition: vmbus.h:483
int(* probe)(struct vmbus_device *vmdev)
Probe device.
Definition: vmbus.h:531
void(* remove)(struct vmbus_device *vmdev)
Remove device.
Definition: vmbus.h:542
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
void(* signal)(struct vmbus_device *vmdev)
Signal channel.
Definition: vmbus.h:492
struct list_head pages
List of transfer page sets.
Definition: vmbus.h:512
struct vmbus_message_header header
Common message header.
Definition: vmbus.h:242
static void vmbus_signal_monitor(struct vmbus_device *vmdev)
Signal channel via monitor page.
Definition: vmbus.c:574
#define BUS_TYPE_HV
Hyper-V bus type.
Definition: device.h:67

References device_description::bus_type, BUS_TYPE_HV, channel, vmbus_offer_channel::channel, vmbus_device::channel, device::children, cpu_to_le32, DBGC, DBGC2, device::desc, vmbus_device::dev, vmbus_device::driver, device::driver_name, ENOMEM, EPROTO, free, header, vmbus_message::header, vmbus_device::hv, INIT_LIST_HEAD, vmbus_offer_channel::instance, vmbus_device::instance, le32_to_cpu, list_add_tail, list_del, list_for_each_entry, list_for_each_entry_continue_reverse, list_for_each_entry_safe, memcpy(), vmbus::message, vmbus_offer_channel::monitor, vmbus_device::monitor, vmbus_offer_channel::monitored, device::name, vmbus_driver::name, vmbus_message::offer, vmbus_device::pages, device::parent, vmbus_driver::probe, rc, vmbus_driver::remove, device::siblings, vmbus_device::signal, snprintf(), strerror(), tmp, type, vmbus_offer_channel::type, uuid_mangle(), uuid_ntoa(), hv_hypervisor::vmbus, VMBUS_ALL_OFFERS_DELIVERED, vmbus_find_driver(), VMBUS_OFFER_CHANNEL, vmbus_post_empty_message(), VMBUS_REQUEST_OFFERS, vmbus_signal_event(), vmbus_signal_monitor(), vmbus_wait_for_any_message(), and zalloc().

Referenced by vmbus_probe().

◆ vmbus_reset_channels()

static int vmbus_reset_channels ( struct hv_hypervisor hv,
struct device parent 
)
static

Reset channels.

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

Definition at line 1270 of file vmbus.c.

1271  {
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 */
1281  if ( ( rc = vmbus_post_empty_message ( hv, VMBUS_REQUEST_OFFERS ) ) !=0)
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
VMBus message header.
Definition: vmbus.h:72
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
struct vmbus_offer_channel offer
"Offer channel" message
Definition: vmbus.h:244
#define le32_to_cpu(value)
Definition: byteswap.h:113
A universally unique ID.
Definition: uuid.h:15
uint8_t monitor
Monitor ID.
Definition: vmbus.h:118
uint32_t channel
Channel ID.
Definition: vmbus.h:116
uint8_t type
Type.
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
A VMBus device.
Definition: vmbus.h:476
static int vmbus_post_empty_message(struct hv_hypervisor *hv, unsigned int type)
Post empty message.
Definition: vmbus.c:95
const union vmbus_message * message
Received message buffer.
Definition: vmbus.h:391
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
uint32_t channel
RNDIS channel.
Definition: netvsc.h:14
A virtual machine bus.
Definition: vmbus.h:383
union uuid type
Channel type.
Definition: vmbus.h:102
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define EPROTO
Protocol error.
Definition: errno.h:624
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
struct vmbus_driver * driver
Driver.
Definition: vmbus.h:515
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition: uuid.c:43
uint8_t monitored
Monitor exists.
Definition: vmbus.h:120
static int vmbus_wait_for_any_message(struct hv_hypervisor *hv)
Wait for received message of any type.
Definition: vmbus.c:108
struct hv_hypervisor * hv
Hyper-V hypervisor.
Definition: vmbus.h:480
#define DBGC2(...)
Definition: compiler.h:522
VMBus "offer channel" message.
Definition: vmbus.h:98
struct list_head children
Devices attached to this device.
Definition: device.h:83
struct ena_aq_header header
Header.
Definition: ena.h:12
struct vmbus * vmbus
Virtual machine bus.
Definition: hyperv.h:211
struct vmbus_message_header header
Common message header.
Definition: vmbus.h:242
int(* reset)(struct vmbus_device *vmdev)
Reset device.
Definition: vmbus.h:537

References channel, vmbus_offer_channel::channel, device::children, cpu_to_le32, DBGC, DBGC2, vmbus_device::dev, vmbus_device::driver, EPROTO, header, vmbus_message::header, vmbus_device::hv, le32_to_cpu, list_for_each_entry, vmbus::message, vmbus_offer_channel::monitor, vmbus_offer_channel::monitored, device::name, vmbus_message::offer, rc, vmbus_driver::reset, device::siblings, strerror(), type, vmbus_offer_channel::type, uuid_ntoa(), hv_hypervisor::vmbus, VMBUS_ALL_OFFERS_DELIVERED, VMBUS_OFFER_CHANNEL, vmbus_post_empty_message(), VMBUS_REQUEST_OFFERS, and vmbus_wait_for_any_message().

Referenced by vmbus_reset().

◆ vmbus_remove_channels()

static void vmbus_remove_channels ( struct hv_hypervisor *hv  __unused,
struct device parent 
)
static

Remove channels.

Parameters
hvHyper-V hypervisor
parentParent device

Definition at line 1339 of file vmbus.c.

1340  {
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 }
struct vmbus_ring * out
Outbound ring buffer.
Definition: vmbus.h:499
struct device dev
Generic iPXE device.
Definition: vmbus.h:478
A VMBus device.
Definition: vmbus.h:476
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
void * packet
Packet buffer.
Definition: vmbus.h:510
#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:447
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
struct vmbus_driver * driver
Driver.
Definition: vmbus.h:515
uint8_t * tmp
Definition: entropy.h:156
struct vmbus_ring * in
Inbound ring buffer.
Definition: vmbus.h:501
struct list_head children
Devices attached to this device.
Definition: device.h:83
void(* remove)(struct vmbus_device *vmdev)
Remove device.
Definition: vmbus.h:542
struct list_head pages
List of transfer page sets.
Definition: vmbus.h:512
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References assert(), device::children, vmbus_device::dev, vmbus_device::driver, free, vmbus_device::in, list_del, list_empty, list_for_each_entry_safe, NULL, vmbus_device::out, vmbus_device::packet, vmbus_device::pages, vmbus_driver::remove, device::siblings, and tmp.

Referenced by vmbus_probe(), and vmbus_remove().

◆ 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:362

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:362

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_gpadl

unsigned int vmbus_gpadl = VMBUS_GPADL_MAGIC
static

Current (i.e.

most recently issued) GPADL ID

Definition at line 54 of file vmbus.c.

Referenced by vmbus_establish_gpadl(), and vmbus_reset().

◆ 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().