51 #define VMBUS_GPADL_MAGIC 0x18ae0000 80 DBGC (
vmbus,
"VMBUS %p could not post message: %s\n",
114 DBGC (
vmbus,
"VMBUS %p failed waiting for message: %s\n",
121 DBGC (
vmbus,
"VMBUS %p invalid message type %d\n",
137 unsigned int type ) {
156 DBGC (
vmbus,
"VMBUS %p ignoring message type %d (expecting " 176 memset ( &initiate, 0,
sizeof ( initiate ) );
185 sizeof ( initiate ) ) ) != 0 )
194 DBGC (
vmbus,
"VMBUS %p requested version not supported\n",
199 DBGC (
vmbus,
"VMBUS %p initiated contact using version %d.%d\n",
296 memset ( &gpadlhdr, 0,
sizeof ( gpadlhdr ) );
300 gpadlhdr.gpadlhdr.range_len =
302 sizeof ( gpadlhdr.pfn ) ) );
306 for ( i = 0 ; i < pfn_count ; i++ )
311 sizeof ( gpadlhdr ) ) ) != 0 )
320 DBGC ( vmdev,
"VMBUS %s unexpected GPADL channel %d\n",
325 DBGC ( vmdev,
"VMBUS %s unexpected GPADL ID %#08x\n",
329 if ( created->
status != 0 ) {
330 DBGC ( vmdev,
"VMBUS %s GPADL creation failed: %#08x\n",
335 DBGC ( vmdev,
"VMBUS %s GPADL %#08x is [%08lx,%08lx)\n",
364 memset ( &teardown, 0,
sizeof ( teardown ) );
371 sizeof ( teardown ) ) ) != 0 )
380 DBGC ( vmdev,
"VMBUS %s unexpected GPADL ID %#08x\n",
405 size_t out_len,
size_t in_len,
size_t mtu ) {
420 assert ( ( out_len & ( out_len - 1 ) ) == 0 );
422 assert ( ( in_len & ( in_len - 1 ) ) == 0 );
430 goto err_alloc_packet;
434 len = (
sizeof ( *vmdev->
out ) + out_len +
435 sizeof ( *vmdev->
in ) + in_len );
463 sizeof (
open ) ) ) != 0 )
464 goto err_post_message;
469 goto err_wait_for_message;
473 DBGC ( vmdev,
"VMBUS %s unexpected opened channel %#08x\n",
476 goto err_check_response;
478 if ( opened->
id != open_id ) {
479 DBGC ( vmdev,
"VMBUS %s unexpected open ID %#08x\n",
482 goto err_check_response;
484 if ( opened->
status != 0 ) {
485 DBGC ( vmdev,
"VMBUS %s open failed: %#08x\n",
488 goto err_check_response;
495 vmdev->
in = ( ring +
sizeof ( *vmdev->
out ) + out_len );
501 DBGC ( vmdev,
"VMBUS %s channel GPADL %#08x ring " 502 "[%#08lx,%#08lx,%#08lx)\n", vmdev->
dev.
name, vmdev->
gpadl,
508 err_wait_for_message:
537 sizeof (
close ) ) ) != 0 ) {
538 DBGC ( vmdev,
"VMBUS %s failed to close: %s\n",
547 DBGC ( vmdev,
"VMBUS %s failed to tear down channel GPADL: " 557 sizeof ( *vmdev->
in ) + vmdev->
in_len );
566 DBGC ( vmdev,
"VMBUS %s closed\n", vmdev->
dev.
name );
599 DBGC ( vmdev,
"VMBUS %s could not signal event: %s\n",
618 const void *
data,
size_t len ) {
633 return ( ( prod +
len ) & ( vmdev->
out_len - 1 ) );
679 const void *
data,
size_t len ) {
682 static uint8_t padding[ 8 - 1 ];
699 footer_len =
sizeof ( footer );
700 ring_len = ( header_len +
len +
pad_len + footer_len );
708 DBGC ( vmdev,
"VMBUS %s ring buffer full\n", vmdev->
dev.
name );
720 DBGC2 ( vmdev,
"VMBUS %s sending:\n", vmdev->
dev.
name );
742 if (
cons != old_prod )
766 const void *
data,
size_t len ) {
813 header->gpa.header.xid = xid;
814 header->gpa.range_count = 1;
817 for ( i = 0 ; i < pfn_count ; i++ )
835 const void *
data,
size_t len ) {
887 DBGC ( vmdev,
"VMBUS %s unrecognised page set ID %#04x\n",
910 unsigned int range_count;
926 for ( i = 0 ; i < range_count ; i++ ) {
935 DBGC ( vmdev,
"VMBUS %s could not allocate %zd-byte " 947 DBGC ( vmdev,
"VMBUS %s could not populate I/O buffer " 948 "range [%zd,%zd): %s\n",
1000 if ( header_len <
sizeof ( *
header ) ) {
1001 DBGC ( vmdev,
"VMBUS %s received underlength header (%zd " 1002 "bytes)\n", vmdev->
dev.
name, header_len );
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 );
1018 ( ring_len -
sizeof ( *
header ) ) );
1019 DBGC2 ( vmdev,
"VMBUS %s received:\n", vmdev->
dev.
name );
1036 data = ( ( (
void * )
header ) + header_len );
1037 switch (
header->type ) {
1042 DBGC ( vmdev,
"VMBUS %s could not handle control " 1052 DBGC ( vmdev,
"VMBUS %s could not handle data packet: " 1061 DBGC ( vmdev,
"VMBUS %s could not handle completion: " 1069 DBGC ( vmdev,
"VMBUS %s could not handle cancellation: " 1076 DBGC ( vmdev,
"VMBUS %s unknown packet type %d\n",
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,
1105 if ( in_prod != in_cons ) {
1106 in_len = ( ( in_prod - in_cons ) &
1109 if (
first > in_len )
1141 struct device *parent ) {
1146 union uuid instance;
1155 goto err_post_message;
1162 goto err_wait_for_any_message;
1186 vmdev =
zalloc (
sizeof ( *vmdev ) );
1189 goto err_alloc_vmdev;
1212 DBGC ( vmdev,
"VMBUS %s has driver \"%s\"\n",
1215 }
else if (
header->type ==
1222 DBGC (
vmbus,
"VMBUS %p unexpected offer response type " 1225 goto err_unexpected_offer;
1235 DBGC ( vmdev,
"VMBUS %s could not probe: %s\n",
1249 err_unexpected_offer:
1251 err_wait_for_any_message:
1271 struct device *parent ) {
1307 }
else if (
header->type ==
1314 DBGC (
vmbus,
"VMBUS %p unexpected offer response type " 1323 DBGC ( vmdev,
"VMBUS %s could not reset: %s\n",
1340 struct device *parent ) {
1391 goto err_alloc_pages;
1398 goto err_negotiate_version;
1402 goto err_probe_channels;
1409 err_negotiate_version:
uint32_t channel
Channel ID.
#define EINVAL
Invalid argument.
struct arbelprm_rc_send_wqe rc
struct vmbus_ring * out
Outbound ring buffer.
uint8_t out[PAGE_SIZE/2]
Outbound interrupts.
int vmbus_send_completion(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send completion packet via ring buffer.
uint16_t pageset
Page set ID.
#define iob_put(iobuf, len)
struct device dev
Generic iPXE device.
static int vmbus_has_data(struct vmbus_device *vmdev)
Check if data is present in ring buffer.
struct vmbus_offer_channel offer
"Offer channel" message
static unsigned int unsigned int bit
#define le32_to_cpu(value)
int hv_wait_for_message(struct hv_hypervisor *hv, unsigned int sintx)
Wait for received message.
struct hv_monitor_trigger trigger[4]
Trigger groups.
int(* recv_control)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received control packet.
#define list_add(new, head)
Add a new entry to the head of a list.
int(* recv_data)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct list_head *list)
Handle received data packet.
uint32_t first
First block in range.
uint8_t monitor
Monitor ID.
struct list_head list
List of all transfer page sets.
struct vmbus_channel_operations * op
Channel operations.
int(* recv_completion)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received completion packet.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
uint32_t channel
Channel ID.
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.
uint32_t type
Operating system type.
#define VMBUS_MESSAGE_TYPE
VMBus message type.
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
static int vmbus_reset_channels(struct hv_hypervisor *hv, struct device *parent)
Reset channels.
int vmbus_reset(struct hv_hypervisor *hv, struct device *parent)
Reset Hyper-V virtual machine bus.
#define ENOENT
No such file or directory.
unsigned long long uint64_t
static void *__malloc malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
struct vmbus_message_header header
Message header.
static int vmbus_send(struct vmbus_device *vmdev, struct vmbus_packet_header *header, const void *data, size_t len)
Send packet via ring buffer.
uint32_t out_len
Outbound ring buffer length.
struct vmbus_xfer_pages_operations * op
Page set operations.
#define PAGE_SIZE
Page size.
static int vmbus_post_empty_message(struct hv_hypervisor *hv, unsigned int type)
Post empty message.
uint8_t data[240]
Message.
uint32_t status
Creation status.
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
VMBus "open channel" message.
struct device * parent
Bus device.
VMBus "GPADL created" message.
struct vmbus_gpadl_torndown torndown
"GPADL torndown" message
static size_t vmbus_produce(struct vmbus_device *vmdev, size_t prod, const void *data, size_t len)
Fill outbound ring buffer.
static int vmbus_initiate_contact(struct hv_hypervisor *hv, unsigned int raw)
Initiate contact.
#define ENOTSUP
Operation not supported.
A doubly-linked list entry (or list head)
VMBus "version response" message.
Dynamic memory allocation.
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.
#define list_empty(list)
Test whether a list is empty.
static void uuid_mangle(union uuid *uuid)
Change UUID endianness.
Hyper-V virtual machine bus.
const union vmbus_message * message
Received message buffer.
Guest physical address range descriptor.
void vmbus_remove(struct hv_hypervisor *hv, struct device *parent)
Remove Hyper-V virtual machine bus.
#define list_del(list)
Delete an entry from a list.
struct hv_message received
Received message.
#define ENOMEM
Not enough space.
uint32_t channel
Channel ID.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint32_t prod
Producer index (modulo ring length)
u32 version
Driver version.
uint32_t userptr_t
A pointer to a user buffer.
uint16_t group
Type of event.
uint16_t pageset
Page set ID (in protocol byte order)
static int vmbus_gpadl_is_obsolete(unsigned int gpadl)
Check if GPADL is obsolete.
uint32_t cons
Consumer index (modulo ring length)
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
uint32_t intr_mask
Interrupt mask.
int hv_alloc_pages(struct hv_hypervisor *hv,...)
Allocate zeroed pages.
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
static size_t vmbus_consume(struct vmbus_device *vmdev, size_t cons, void *data, size_t len)
Consume inbound ring buffer.
#define __unused
Declare a variable or data structure as unused.
uint32_t in_len
Inbound ring buffer length.
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
void * packet
Packet buffer.
static int vmbus_post_message(struct hv_hypervisor *hv, const struct vmbus_message_header *header, size_t len)
Post message.
uint32_t channel
RNDIS channel.
static struct vmbus_driver * vmbus_find_driver(const union uuid *type)
Find driver for VMBus device.
static unsigned int vmbus_gpadl
Current (i.e.
const char * driver_name
Driver name.
#define VMBUS_DRIVERS
VMBus device driver table.
union uuid type
Channel type.
VMBus "GPADL torndown" message.
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
#define cpu_to_le32(value)
#define EPROTO
Protocol error.
struct vmbus_gpadl_created created
"GPADL created" message
static __always_inline void struct pci_range * range
uint8_t data[0]
Ring buffer contents.
static unsigned int hv_pfn_count(physaddr_t data, size_t len)
Calculate the number of pages covering an address range.
#define ERANGE
Result too large.
char * strerror(int errno)
Retrieve string representation of error number.
static void(* free)(struct refcnt *refcnt))
uint16_t minor
Minor version.
void * zalloc(size_t size)
Allocate cleared memory.
uint16_t cons
Consumer index.
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
struct list_head siblings
Devices on the same bus.
union uuid type
Device type.
struct vmbus_driver * driver
Driver.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
uint32_t channel
Channel ID.
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
struct hv_monitor * monitor_in
Inbound notifications.
void set_bit(unsigned int bit, volatile void *bits)
static int vmbus_wait_for_message(struct hv_hypervisor *hv, unsigned int type)
Wait for received message of a specified type, ignoring any others.
int vmbus_gpadl_teardown(struct vmbus_device *vmdev, unsigned int gpadl)
Tear down GPA descriptor list.
struct vmbus_ring * in
Inbound ring buffer.
#define le16_to_cpu(value)
void * malloc(size_t size)
Allocate memory.
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
#define VMBUS_GPADL_MAGIC
VMBus initial GPADL ID.
int(* copy)(struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
Copy data from transfer page.
uint8_t monitored
Monitor exists.
static int vmbus_unload(struct hv_hypervisor *hv)
Terminate contact.
int vmbus_send_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Send cancellation packet via ring buffer.
union hv_message_buffer * message
Message buffer.
int vmbus_poll(struct vmbus_device *vmdev)
Poll ring buffer.
struct vmbus_version_response version
"Version response" message
#define list_for_each_entry_continue_reverse(pos, head, member)
Iterate over entries in a list in reverse, starting after current position.
static uint16_t struct vmbus_xfer_pages_operations * op
#define INIT_LIST_HEAD(list)
Initialise a list head.
static int vmbus_wait_for_any_message(struct hv_hypervisor *hv)
Wait for received message of any type.
int vmbus_send_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send control packet via ring buffer.
VMBus "open channel result" message.
unsigned int bus_type
Bus type.
static int vmbus_negotiate_version(struct hv_hypervisor *hv)
Negotiate protocol version.
unsigned int channel
Channel ID.
struct list_head list
List of which this buffer is a member.
unsigned int monitor
Monitor ID.
VMBus "close channel" message.
#define ENOBUFS
No buffer space available.
uint64_t pfn[0]
Page frame numbers.
struct hv_hypervisor * hv
Hyper-V hypervisor.
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
#define VMBUS_MESSAGE_SINT
VMBus message synthetic interrupt.
VMBus channel operations.
static int vmbus_probe_channels(struct hv_hypervisor *hv, struct device *parent)
Probe channels.
unsigned int gpadl
Ring buffer GPADL ID.
void * data
Start of data.
VMBus "offer channel" message.
struct list_head children
Devices attached to this device.
static void vmbus_signal_event(struct vmbus_device *vmdev)
Signal channel via hypervisor event.
struct vmbus_open_channel_result opened
"Open channel result" message
struct ena_aq_header header
Header.
struct vmbus_interrupt * intr
Interrupt page.
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
#define cpu_to_le16(value)
int open(const char *uri_string)
Open file.
uint8_t data[48]
Additional event data.
struct device_description desc
Device description.
union uuid instance
Channel instance.
union uuid instance
Channel instance.
int(* probe)(struct vmbus_device *vmdev)
Probe device.
void(* remove)(struct vmbus_device *vmdev)
Remove device.
uint16_t major
Major version.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
static void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
uint16_t offset
Offset to command line.
void mb(void)
Memory barrier.
struct hv_monitor * monitor_out
Outbound notifications.
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
int vmbus_probe(struct hv_hypervisor *hv, struct device *parent)
Probe Hyper-V virtual machine bus.
struct vmbus * vmbus
Virtual machine bus.
VMBus "GPADL teardown" message.
void vmbus_close(struct vmbus_device *vmdev)
Close VMBus channel.
void(* signal)(struct vmbus_device *vmdev)
Signal channel.
static struct evtchn_close * close
#define VMBUS_EVENT_ID
VMBus event connection ID.
int vmbus_establish_gpadl(struct vmbus_device *vmdev, userptr_t data, size_t len)
Establish GPA descriptor list.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void vmbus_dump_channel(struct vmbus_device *vmdev)
Dump channel status (for debugging)
#define le64_to_cpu(value)
struct hv_monitor_trigger trigger[4]
Trigger groups.
unsigned int vmbus_obsolete_gpadl
Obsolete GPADL ID threshold.
uint32_t pending
Pending events.
static void vmbus_remove_channels(struct hv_hypervisor *hv __unused, struct device *parent)
Remove channels.
struct list_head pages
List of transfer page sets.
struct vmbus_message_header header
Common message header.
size_t mtu
Maximum expected data packet length.
static void vmbus_signal_monitor(struct vmbus_device *vmdev)
Signal channel via monitor page.
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
#define NULL
NULL pointer (VOID *)
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.
static __always_inline int off_t userptr_t second
#define VMBUS_MESSAGE_ID
VMBus message connection ID.
int(* recv_cancellation)(struct vmbus_device *vmdev, uint64_t xid)
Handle received cancellation packet.
#define BUS_TYPE_HV
Hyper-V bus type.
static struct vmbus_xfer_pages * vmbus_xfer_pages(struct vmbus_device *vmdev, uint16_t pageset)
Get transfer page set from pageset ID.
void * memset(void *dest, int character, size_t len) __nonnull
int(* reset)(struct vmbus_device *vmdev)
Reset device.