summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/hyperv/include/hyperv.h168
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel.c580
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c108
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c40
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h61
-rw-r--r--sys/dev/hyperv/vmbus/hyperv.c45
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c25
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_reg.h87
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h1
9 files changed, 321 insertions, 794 deletions
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index 48e2258..680717d 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -179,8 +179,6 @@ typedef struct hv_vmbus_channel_offer {
} __packed hv_vmbus_channel_offer;
-typedef uint32_t hv_gpadl_handle;
-
typedef struct {
uint16_t type;
uint16_t data_offset8;
@@ -352,14 +350,6 @@ typedef struct {
} __packed hv_vmbus_channel_query_vmbus_version;
/*
- * VMBus Version Supported parameters
- */
-typedef struct {
- hv_vmbus_channel_msg_header header;
- hv_bool_uint8_t version_supported;
-} __packed hv_vmbus_channel_version_supported;
-
-/*
* Channel Offer parameters
*/
typedef struct {
@@ -397,171 +387,13 @@ typedef struct
uint32_t child_rel_id;
} __packed hv_vmbus_channel_rescind_offer;
-
-/*
- * Request Offer -- no parameters, SynIC message contains the partition ID
- *
- * Set Snoop -- no parameters, SynIC message contains the partition ID
- *
- * Clear Snoop -- no parameters, SynIC message contains the partition ID
- *
- * All Offers Delivered -- no parameters, SynIC message contains the
- * partition ID
- *
- * Flush Client -- no parameters, SynIC message contains the partition ID
- */
-
-
-/*
- * Open Channel parameters
- */
-typedef struct
-{
- hv_vmbus_channel_msg_header header;
-
- /*
- * Identifies the specific VMBus channel that is being opened.
- */
- uint32_t child_rel_id;
-
- /*
- * ID making a particular open request at a channel offer unique.
- */
- uint32_t open_id;
-
- /*
- * GPADL for the channel's ring buffer.
- */
- hv_gpadl_handle ring_buffer_gpadl_handle;
-
- /*
- * Before win8, all incoming channel interrupts are only
- * delivered on cpu 0. Setting this value to 0 would
- * preserve the earlier behavior.
- */
- uint32_t target_vcpu;
-
- /*
- * The upstream ring buffer begins at offset zero in the memory described
- * by ring_buffer_gpadl_handle. The downstream ring buffer follows it at
- * this offset (in pages).
- */
- uint32_t downstream_ring_buffer_page_offset;
-
- /*
- * User-specific data to be passed along to the server endpoint.
- */
- uint8_t user_data[HV_MAX_USER_DEFINED_BYTES];
-
-} __packed hv_vmbus_channel_open_channel;
-
-typedef uint32_t hv_nt_status;
-
-/*
- * Open Channel Result parameters
- */
-typedef struct
-{
- hv_vmbus_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t open_id;
- hv_nt_status status;
-} __packed hv_vmbus_channel_open_result;
-
-/*
- * Close channel parameters
- */
-typedef struct
-{
- hv_vmbus_channel_msg_header header;
- uint32_t child_rel_id;
-} __packed hv_vmbus_channel_close_channel;
-
-/*
- * Channel Message GPADL
- */
-#define HV_GPADL_TYPE_RING_BUFFER 1
-#define HV_GPADL_TYPE_SERVER_SAVE_AREA 2
-#define HV_GPADL_TYPE_TRANSACTION 8
-
-/*
- * The number of PFNs in a GPADL message is defined by the number of pages
- * that would be spanned by byte_count and byte_offset. If the implied number
- * of PFNs won't fit in this packet, there will be a follow-up packet that
- * contains more
- */
-
-typedef struct {
- hv_vmbus_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t gpadl;
- uint16_t range_buf_len;
- uint16_t range_count;
- hv_gpa_range range[0];
-} __packed hv_vmbus_channel_gpadl_header;
-
-/*
- * This is the follow-up packet that contains more PFNs
- */
-typedef struct {
- hv_vmbus_channel_msg_header header;
- uint32_t message_number;
- uint32_t gpadl;
- uint64_t pfn[0];
-} __packed hv_vmbus_channel_gpadl_body;
-
-typedef struct {
- hv_vmbus_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t gpadl;
- uint32_t creation_status;
-} __packed hv_vmbus_channel_gpadl_created;
-
-typedef struct {
- hv_vmbus_channel_msg_header header;
- uint32_t child_rel_id;
- uint32_t gpadl;
-} __packed hv_vmbus_channel_gpadl_teardown;
-
-typedef struct {
- hv_vmbus_channel_msg_header header;
- uint32_t gpadl;
-} __packed hv_vmbus_channel_gpadl_torndown;
-
typedef struct {
hv_vmbus_channel_msg_header header;
uint32_t child_rel_id;
} __packed hv_vmbus_channel_relid_released;
-typedef hv_vmbus_channel_msg_header hv_vmbus_channel_unload;
-
#define HW_MACADDR_LEN 6
-/*
- * Fixme: Added to quiet "typeof" errors involving hv_vmbus.h when
- * the including C file was compiled with "-std=c99".
- */
-#ifndef typeof
-#define typeof __typeof
-#endif
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
-typedef void *hv_vmbus_handle;
-
-#ifndef CONTAINING_RECORD
-#define CONTAINING_RECORD(address, type, field) ((type *)( \
- (uint8_t *)(address) - \
- (uint8_t *)(&((type *)0)->field)))
-#endif /* CONTAINING_RECORD */
-
-
-#define container_of(ptr, type, member) ({ \
- __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
enum {
HV_VMBUS_IVAR_TYPE,
HV_VMBUS_IVAR_INSTANCE,
diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c
index 3378450..14290fd 100644
--- a/sys/dev/hyperv/vmbus/hv_channel.c
+++ b/sys/dev/hyperv/vmbus/hv_channel.c
@@ -49,14 +49,6 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
-static int vmbus_channel_create_gpadl_header(
- /* must be phys and virt contiguous*/
- void* contig_buffer,
- /* page-size multiple */
- uint32_t size,
- hv_vmbus_channel_msg_info** msg_info,
- uint32_t* message_count);
-
static void vmbus_channel_set_event(hv_vmbus_channel* channel);
static void VmbusProcessChannelEvent(void* channel, int pending);
@@ -182,11 +174,21 @@ hv_vmbus_channel_open(
hv_vmbus_pfn_channel_callback pfn_on_channel_callback,
void* context)
{
-
+ struct vmbus_softc *sc = new_channel->vmbus_sc;
+ const struct vmbus_chanmsg_chopen_resp *resp;
+ const struct vmbus_message *msg;
+ struct vmbus_chanmsg_chopen *req;
+ struct vmbus_msghc *mh;
+ uint32_t status;
int ret = 0;
void *in, *out;
- hv_vmbus_channel_open_channel* open_msg;
- hv_vmbus_channel_msg_info* open_info;
+
+ if (user_data_len > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) {
+ device_printf(sc->vmbus_dev,
+ "invalid udata len %u for chan%u\n",
+ user_data_len, new_channel->offer_msg.child_rel_id);
+ return EINVAL;
+ }
mtx_lock(&new_channel->sc_lock);
if (new_channel->state == HV_CHANNEL_OPEN_STATE) {
@@ -248,381 +250,231 @@ hv_vmbus_channel_open(
send_ring_buffer_size + recv_ring_buffer_size,
&new_channel->ring_buffer_gpadl_handle);
- /**
- * Create and init the channel open message
+ /*
+ * Open channel w/ the bufring GPADL on the target CPU.
*/
- open_info = (hv_vmbus_channel_msg_info*) malloc(
- sizeof(hv_vmbus_channel_msg_info) +
- sizeof(hv_vmbus_channel_open_channel),
- M_DEVBUF,
- M_NOWAIT);
- KASSERT(open_info != NULL,
- ("Error VMBUS: malloc failed to allocate Open Channel message!"));
-
- if (open_info == NULL)
- return (ENOMEM);
-
- sema_init(&open_info->wait_sema, 0, "Open Info Sema");
-
- open_msg = (hv_vmbus_channel_open_channel*) open_info->msg;
- open_msg->header.message_type = HV_CHANNEL_MESSAGE_OPEN_CHANNEL;
- open_msg->open_id = new_channel->offer_msg.child_rel_id;
- open_msg->child_rel_id = new_channel->offer_msg.child_rel_id;
- open_msg->ring_buffer_gpadl_handle =
- new_channel->ring_buffer_gpadl_handle;
- open_msg->downstream_ring_buffer_page_offset = send_ring_buffer_size
- >> PAGE_SHIFT;
- open_msg->target_vcpu = new_channel->target_vcpu;
+ mh = vmbus_msghc_get(sc, sizeof(*req));
+ if (mh == NULL) {
+ device_printf(sc->vmbus_dev,
+ "can not get msg hypercall for chopen(chan%u)\n",
+ new_channel->offer_msg.child_rel_id);
+ return ENXIO;
+ }
+ req = vmbus_msghc_dataptr(mh);
+ req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHOPEN;
+ req->chm_chanid = new_channel->offer_msg.child_rel_id;
+ req->chm_openid = new_channel->offer_msg.child_rel_id;
+ req->chm_gpadl = new_channel->ring_buffer_gpadl_handle;
+ req->chm_vcpuid = new_channel->target_vcpu;
+ req->chm_rxbr_pgofs = send_ring_buffer_size >> PAGE_SHIFT;
if (user_data_len)
- memcpy(open_msg->user_data, user_data, user_data_len);
-
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_INSERT_TAIL(
- &hv_vmbus_g_connection.channel_msg_anchor,
- open_info,
- msg_list_entry);
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
-
- ret = hv_vmbus_post_message(
- open_msg, sizeof(hv_vmbus_channel_open_channel));
-
- if (ret != 0)
- goto cleanup;
+ memcpy(req->chm_udata, user_data, user_data_len);
+
+ ret = vmbus_msghc_exec(sc, mh);
+ if (ret != 0) {
+ device_printf(sc->vmbus_dev,
+ "chopen(chan%u) msg hypercall exec failed: %d\n",
+ new_channel->offer_msg.child_rel_id, ret);
+ vmbus_msghc_put(sc, mh);
+ return ret;
+ }
- ret = sema_timedwait(&open_info->wait_sema, 5 * hz); /* KYS 5 seconds */
+ msg = vmbus_msghc_wait_result(sc, mh);
+ resp = (const struct vmbus_chanmsg_chopen_resp *)msg->msg_data;
+ status = resp->chm_status;
- if (ret) {
- if(bootverbose)
- printf("VMBUS: channel <%p> open timeout.\n", new_channel);
- goto cleanup;
- }
+ vmbus_msghc_put(sc, mh);
- if (open_info->response.open_result.status == 0) {
- new_channel->state = HV_CHANNEL_OPENED_STATE;
- if(bootverbose)
- printf("VMBUS: channel <%p> open success.\n", new_channel);
+ if (status == 0) {
+ new_channel->state = HV_CHANNEL_OPENED_STATE;
+ if (bootverbose) {
+ device_printf(sc->vmbus_dev, "chan%u opened\n",
+ new_channel->offer_msg.child_rel_id);
+ }
} else {
- if(bootverbose)
- printf("Error VMBUS: channel <%p> open failed - %d!\n",
- new_channel, open_info->response.open_result.status);
+ device_printf(sc->vmbus_dev, "failed to open chan%u\n",
+ new_channel->offer_msg.child_rel_id);
+ ret = ENXIO;
}
-
- cleanup:
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_REMOVE(
- &hv_vmbus_g_connection.channel_msg_anchor,
- open_info,
- msg_list_entry);
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
- sema_destroy(&open_info->wait_sema);
- free(open_info, M_DEVBUF);
-
return (ret);
}
/**
- * @brief Create a gpadl for the specified buffer
+ * @brief Establish a GPADL for the specified buffer
*/
-static int
-vmbus_channel_create_gpadl_header(
- void* contig_buffer,
- uint32_t size, /* page-size multiple */
- hv_vmbus_channel_msg_info** msg_info,
- uint32_t* message_count)
+int
+hv_vmbus_channel_establish_gpadl(struct hv_vmbus_channel *channel,
+ void *contig_buffer, uint32_t size, uint32_t *gpadl0)
{
- int i;
- int page_count;
- unsigned long long pfn;
- uint32_t msg_size;
- hv_vmbus_channel_gpadl_header* gpa_header;
- hv_vmbus_channel_gpadl_body* gpadl_body;
- hv_vmbus_channel_msg_info* msg_header;
- hv_vmbus_channel_msg_info* msg_body;
+ struct vmbus_softc *sc = channel->vmbus_sc;
+ struct vmbus_msghc *mh;
+ struct vmbus_chanmsg_gpadl_conn *req;
+ const struct vmbus_message *msg;
+ size_t reqsz;
+ uint32_t gpadl, status;
+ int page_count, range_len, i, cnt, error;
+ uint64_t page_id, paddr;
- int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
+ /*
+ * Preliminary checks.
+ */
+ KASSERT((size & PAGE_MASK) == 0,
+ ("invalid GPA size %u, not multiple page size", size));
page_count = size >> PAGE_SHIFT;
- pfn = hv_get_phys_addr(contig_buffer) >> PAGE_SHIFT;
-
- /*do we need a gpadl body msg */
- pfnSize = HV_MAX_SIZE_CHANNEL_MESSAGE
- - sizeof(hv_vmbus_channel_gpadl_header)
- - sizeof(hv_gpa_range);
- pfnCount = pfnSize / sizeof(uint64_t);
-
- if (page_count > pfnCount) { /* if(we need a gpadl body) */
- /* fill in the header */
- msg_size = sizeof(hv_vmbus_channel_msg_info)
- + sizeof(hv_vmbus_channel_gpadl_header)
- + sizeof(hv_gpa_range)
- + pfnCount * sizeof(uint64_t);
- msg_header = malloc(msg_size, M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(
- msg_header != NULL,
- ("Error VMBUS: malloc failed to allocate Gpadl Message!"));
- if (msg_header == NULL)
- return (ENOMEM);
-
- TAILQ_INIT(&msg_header->sub_msg_list_anchor);
- msg_header->message_size = msg_size;
-
- gpa_header = (hv_vmbus_channel_gpadl_header*) msg_header->msg;
- gpa_header->range_count = 1;
- gpa_header->range_buf_len = sizeof(hv_gpa_range)
- + page_count * sizeof(uint64_t);
- gpa_header->range[0].byte_offset = 0;
- gpa_header->range[0].byte_count = size;
- for (i = 0; i < pfnCount; i++) {
- gpa_header->range[0].pfn_array[i] = pfn + i;
- }
- *msg_info = msg_header;
- *message_count = 1;
-
- pfnSum = pfnCount;
- pfnLeft = page_count - pfnCount;
-
- /*
- * figure out how many pfns we can fit
- */
- pfnSize = HV_MAX_SIZE_CHANNEL_MESSAGE
- - sizeof(hv_vmbus_channel_gpadl_body);
- pfnCount = pfnSize / sizeof(uint64_t);
-
- /*
- * fill in the body
- */
- while (pfnLeft) {
- if (pfnLeft > pfnCount) {
- pfnCurr = pfnCount;
- } else {
- pfnCurr = pfnLeft;
- }
-
- msg_size = sizeof(hv_vmbus_channel_msg_info) +
- sizeof(hv_vmbus_channel_gpadl_body) +
- pfnCurr * sizeof(uint64_t);
- msg_body = malloc(msg_size, M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(
- msg_body != NULL,
- ("Error VMBUS: malloc failed to allocate Gpadl msg_body!"));
- if (msg_body == NULL)
- return (ENOMEM);
-
- msg_body->message_size = msg_size;
- (*message_count)++;
- gpadl_body =
- (hv_vmbus_channel_gpadl_body*) msg_body->msg;
- /*
- * gpadl_body->gpadl = kbuffer;
- */
- for (i = 0; i < pfnCurr; i++) {
- gpadl_body->pfn[i] = pfn + pfnSum + i;
- }
- TAILQ_INSERT_TAIL(
- &msg_header->sub_msg_list_anchor,
- msg_body,
- msg_list_entry);
- pfnSum += pfnCurr;
- pfnLeft -= pfnCurr;
- }
- } else { /* else everything fits in a header */
-
- msg_size = sizeof(hv_vmbus_channel_msg_info) +
- sizeof(hv_vmbus_channel_gpadl_header) +
- sizeof(hv_gpa_range) +
- page_count * sizeof(uint64_t);
- msg_header = malloc(msg_size, M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(
- msg_header != NULL,
- ("Error VMBUS: malloc failed to allocate Gpadl Message!"));
- if (msg_header == NULL)
- return (ENOMEM);
+ paddr = hv_get_phys_addr(contig_buffer);
+ KASSERT((paddr & PAGE_MASK) == 0,
+ ("GPA is not page aligned %jx", (uintmax_t)paddr));
+ page_id = paddr >> PAGE_SHIFT;
- msg_header->message_size = msg_size;
-
- gpa_header = (hv_vmbus_channel_gpadl_header*) msg_header->msg;
- gpa_header->range_count = 1;
- gpa_header->range_buf_len = sizeof(hv_gpa_range) +
- page_count * sizeof(uint64_t);
- gpa_header->range[0].byte_offset = 0;
- gpa_header->range[0].byte_count = size;
- for (i = 0; i < page_count; i++) {
- gpa_header->range[0].pfn_array[i] = pfn + i;
- }
-
- *msg_info = msg_header;
- *message_count = 1;
+ range_len = __offsetof(struct vmbus_gpa_range, gpa_page[page_count]);
+ /*
+ * We don't support multiple GPA ranges.
+ */
+ if (range_len > UINT16_MAX) {
+ device_printf(sc->vmbus_dev, "GPA too large, %d pages\n",
+ page_count);
+ return EOPNOTSUPP;
}
- return (0);
-}
-
-/**
- * @brief Establish a GPADL for the specified buffer
- */
-int
-hv_vmbus_channel_establish_gpadl(
- hv_vmbus_channel* channel,
- void* contig_buffer,
- uint32_t size, /* page-size multiple */
- uint32_t* gpadl_handle)
-
-{
- int ret = 0;
- hv_vmbus_channel_gpadl_header* gpadl_msg;
- hv_vmbus_channel_gpadl_body* gpadl_body;
- hv_vmbus_channel_msg_info* msg_info;
- hv_vmbus_channel_msg_info* sub_msg_info;
- uint32_t msg_count;
- hv_vmbus_channel_msg_info* curr;
- uint32_t next_gpadl_handle;
-
- next_gpadl_handle = atomic_fetchadd_int(
+ /*
+ * Allocate GPADL id.
+ */
+ gpadl = atomic_fetchadd_int(
&hv_vmbus_g_connection.next_gpadl_handle, 1);
+ *gpadl0 = gpadl;
- ret = vmbus_channel_create_gpadl_header(
- contig_buffer, size, &msg_info, &msg_count);
+ /*
+ * Connect this GPADL to the target channel.
+ *
+ * NOTE:
+ * Since each message can only hold small set of page
+ * addresses, several messages may be required to
+ * complete the connection.
+ */
+ if (page_count > VMBUS_CHANMSG_GPADL_CONN_PGMAX)
+ cnt = VMBUS_CHANMSG_GPADL_CONN_PGMAX;
+ else
+ cnt = page_count;
+ page_count -= cnt;
+
+ reqsz = __offsetof(struct vmbus_chanmsg_gpadl_conn,
+ chm_range.gpa_page[cnt]);
+ mh = vmbus_msghc_get(sc, reqsz);
+ if (mh == NULL) {
+ device_printf(sc->vmbus_dev,
+ "can not get msg hypercall for gpadl->chan%u\n",
+ channel->offer_msg.child_rel_id);
+ return EIO;
+ }
- if(ret != 0) {
- /*
- * XXX
- * We can _not_ even revert the above incremental,
- * if multiple GPADL establishments are running
- * parallelly, decrement the global next_gpadl_handle
- * is calling for _big_ trouble. A better solution
- * is to have a 0-based GPADL id bitmap ...
- */
- return ret;
+ req = vmbus_msghc_dataptr(mh);
+ req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_CONN;
+ req->chm_chanid = channel->offer_msg.child_rel_id;
+ req->chm_gpadl = gpadl;
+ req->chm_range_len = range_len;
+ req->chm_range_cnt = 1;
+ req->chm_range.gpa_len = size;
+ req->chm_range.gpa_ofs = 0;
+ for (i = 0; i < cnt; ++i)
+ req->chm_range.gpa_page[i] = page_id++;
+
+ error = vmbus_msghc_exec(sc, mh);
+ if (error) {
+ device_printf(sc->vmbus_dev,
+ "gpadl->chan%u msg hypercall exec failed: %d\n",
+ channel->offer_msg.child_rel_id, error);
+ vmbus_msghc_put(sc, mh);
+ return error;
}
- sema_init(&msg_info->wait_sema, 0, "Open Info Sema");
- gpadl_msg = (hv_vmbus_channel_gpadl_header*) msg_info->msg;
- gpadl_msg->header.message_type = HV_CHANNEL_MESSAGEL_GPADL_HEADER;
- gpadl_msg->child_rel_id = channel->offer_msg.child_rel_id;
- gpadl_msg->gpadl = next_gpadl_handle;
+ while (page_count > 0) {
+ struct vmbus_chanmsg_gpadl_subconn *subreq;
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_INSERT_TAIL(
- &hv_vmbus_g_connection.channel_msg_anchor,
- msg_info,
- msg_list_entry);
+ if (page_count > VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX)
+ cnt = VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX;
+ else
+ cnt = page_count;
+ page_count -= cnt;
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
+ reqsz = __offsetof(struct vmbus_chanmsg_gpadl_subconn,
+ chm_gpa_page[cnt]);
+ vmbus_msghc_reset(mh, reqsz);
- ret = hv_vmbus_post_message(
- gpadl_msg,
- msg_info->message_size -
- (uint32_t) sizeof(hv_vmbus_channel_msg_info));
+ subreq = vmbus_msghc_dataptr(mh);
+ subreq->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_SUBCONN;
+ subreq->chm_gpadl = gpadl;
+ for (i = 0; i < cnt; ++i)
+ subreq->chm_gpa_page[i] = page_id++;
- if (ret != 0)
- goto cleanup;
-
- if (msg_count > 1) {
- TAILQ_FOREACH(curr,
- &msg_info->sub_msg_list_anchor, msg_list_entry) {
- sub_msg_info = curr;
- gpadl_body =
- (hv_vmbus_channel_gpadl_body*) sub_msg_info->msg;
-
- gpadl_body->header.message_type =
- HV_CHANNEL_MESSAGE_GPADL_BODY;
- gpadl_body->gpadl = next_gpadl_handle;
-
- ret = hv_vmbus_post_message(
- gpadl_body,
- sub_msg_info->message_size
- - (uint32_t) sizeof(hv_vmbus_channel_msg_info));
- /* if (the post message failed) give up and clean up */
- if(ret != 0)
- goto cleanup;
- }
+ vmbus_msghc_exec_noresult(mh);
}
+ KASSERT(page_count == 0, ("invalid page count %d", page_count));
- ret = sema_timedwait(&msg_info->wait_sema, 5 * hz); /* KYS 5 seconds*/
- if (ret != 0)
- goto cleanup;
-
- *gpadl_handle = gpadl_msg->gpadl;
+ msg = vmbus_msghc_wait_result(sc, mh);
+ status = ((const struct vmbus_chanmsg_gpadl_connresp *)
+ msg->msg_data)->chm_status;
-cleanup:
+ vmbus_msghc_put(sc, mh);
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
- msg_info, msg_list_entry);
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
-
- sema_destroy(&msg_info->wait_sema);
- free(msg_info, M_DEVBUF);
-
- return (ret);
+ if (status != 0) {
+ device_printf(sc->vmbus_dev, "gpadl->chan%u failed: "
+ "status %u\n", channel->offer_msg.child_rel_id, status);
+ return EIO;
+ }
+ return 0;
}
-/**
- * @brief Teardown the specified GPADL handle
+/*
+ * Disconnect the GPA from the target channel
*/
int
-hv_vmbus_channel_teardown_gpdal(
- hv_vmbus_channel* channel,
- uint32_t gpadl_handle)
+hv_vmbus_channel_teardown_gpdal(struct hv_vmbus_channel *chan, uint32_t gpadl)
{
- int ret = 0;
- hv_vmbus_channel_gpadl_teardown* msg;
- hv_vmbus_channel_msg_info* info;
-
- info = (hv_vmbus_channel_msg_info *)
- malloc( sizeof(hv_vmbus_channel_msg_info) +
- sizeof(hv_vmbus_channel_gpadl_teardown),
- M_DEVBUF, M_NOWAIT);
- KASSERT(info != NULL,
- ("Error VMBUS: malloc failed to allocate Gpadl Teardown Msg!"));
- if (info == NULL) {
- ret = ENOMEM;
- goto cleanup;
+ struct vmbus_softc *sc = chan->vmbus_sc;
+ struct vmbus_msghc *mh;
+ struct vmbus_chanmsg_gpadl_disconn *req;
+ int error;
+
+ mh = vmbus_msghc_get(sc, sizeof(*req));
+ if (mh == NULL) {
+ device_printf(sc->vmbus_dev,
+ "can not get msg hypercall for gpa x->chan%u\n",
+ chan->offer_msg.child_rel_id);
+ return EBUSY;
}
- sema_init(&info->wait_sema, 0, "Open Info Sema");
-
- msg = (hv_vmbus_channel_gpadl_teardown*) info->msg;
-
- msg->header.message_type = HV_CHANNEL_MESSAGE_GPADL_TEARDOWN;
- msg->child_rel_id = channel->offer_msg.child_rel_id;
- msg->gpadl = gpadl_handle;
-
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_msg_anchor,
- info, msg_list_entry);
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
-
- ret = hv_vmbus_post_message(msg,
- sizeof(hv_vmbus_channel_gpadl_teardown));
- if (ret != 0)
- goto cleanup;
-
- ret = sema_timedwait(&info->wait_sema, 5 * hz); /* KYS 5 seconds */
+ req = vmbus_msghc_dataptr(mh);
+ req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_DISCONN;
+ req->chm_chanid = chan->offer_msg.child_rel_id;
+ req->chm_gpadl = gpadl;
+
+ error = vmbus_msghc_exec(sc, mh);
+ if (error) {
+ device_printf(sc->vmbus_dev,
+ "gpa x->chan%u msg hypercall exec failed: %d\n",
+ chan->offer_msg.child_rel_id, error);
+ vmbus_msghc_put(sc, mh);
+ return error;
+ }
-cleanup:
- /*
- * Received a torndown response
- */
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
- info, msg_list_entry);
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
- sema_destroy(&info->wait_sema);
- free(info, M_DEVBUF);
+ vmbus_msghc_wait_result(sc, mh);
+ /* Discard result; no useful information */
+ vmbus_msghc_put(sc, mh);
- return (ret);
+ return 0;
}
static void
hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
{
- int ret = 0;
+ struct vmbus_softc *sc = channel->vmbus_sc;
+ struct vmbus_msghc *mh;
+ struct vmbus_chanmsg_chclose *req;
struct taskqueue *rxq = channel->rxq;
- hv_vmbus_channel_close_channel* msg;
- hv_vmbus_channel_msg_info* info;
+ int error;
channel->state = HV_CHANNEL_OPEN_STATE;
@@ -636,20 +488,31 @@ hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
/**
* Send a closing message
*/
- info = (hv_vmbus_channel_msg_info *)
- malloc( sizeof(hv_vmbus_channel_msg_info) +
- sizeof(hv_vmbus_channel_close_channel),
- M_DEVBUF, M_NOWAIT);
- KASSERT(info != NULL, ("VMBUS: malloc failed hv_vmbus_channel_close!"));
- if(info == NULL)
- return;
- msg = (hv_vmbus_channel_close_channel*) info->msg;
- msg->header.message_type = HV_CHANNEL_MESSAGE_CLOSE_CHANNEL;
- msg->child_rel_id = channel->offer_msg.child_rel_id;
+ mh = vmbus_msghc_get(sc, sizeof(*req));
+ if (mh == NULL) {
+ device_printf(sc->vmbus_dev,
+ "can not get msg hypercall for chclose(chan%u)\n",
+ channel->offer_msg.child_rel_id);
+ return;
+ }
+
+ req = vmbus_msghc_dataptr(mh);
+ req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHCLOSE;
+ req->chm_chanid = channel->offer_msg.child_rel_id;
- ret = hv_vmbus_post_message(
- msg, sizeof(hv_vmbus_channel_close_channel));
+ error = vmbus_msghc_exec_noresult(mh);
+ vmbus_msghc_put(sc, mh);
+
+ if (error) {
+ device_printf(sc->vmbus_dev,
+ "chclose(chan%u) msg hypercall exec failed: %d\n",
+ channel->offer_msg.child_rel_id, error);
+ return;
+ } else if (bootverbose) {
+ device_printf(sc->vmbus_dev, "close chan%u\n",
+ channel->offer_msg.child_rel_id);
+ }
/* Tear down the gpadl for the channel's ring buffer */
if (channel->ring_buffer_gpadl_handle) {
@@ -665,8 +528,6 @@ hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
contigfree(channel->ring_buffer_pages, channel->ring_buffer_size,
M_DEVBUF);
-
- free(info, M_DEVBUF);
}
/**
@@ -988,23 +849,6 @@ VmbusProcessChannelEvent(void* context, int pending)
hv_vmbus_channel* channel = (hv_vmbus_channel*)context;
boolean_t is_batched_reading;
- /**
- * Find the channel based on this relid and invokes
- * the channel callback to process the event
- */
-
- if (channel == NULL) {
- return;
- }
- /**
- * To deal with the race condition where we might
- * receive a packet while the relevant driver is
- * being unloaded, dispatch the callback while
- * holding the channel lock. The unloading driver
- * will acquire the same channel lock to set the
- * callback to NULL. This closes the window.
- */
-
if (channel->on_channel_callback != NULL) {
arg = channel->channel_callback_context;
is_batched_reading = channel->batched_reading;
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index 3957d9e..2c322e6 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -421,46 +421,13 @@ vmbus_channel_on_offers_delivered(struct vmbus_softc *sc,
* @brief Open result handler.
*
* This is invoked when we received a response
- * to our channel open request. Find the matching request, copy the
- * response and signal the requesting thread.
+ * to our channel open request.
*/
static void
vmbus_channel_on_open_result(struct vmbus_softc *sc,
const struct vmbus_message *msg)
{
- const hv_vmbus_channel_msg_header *hdr =
- (const hv_vmbus_channel_msg_header *)msg->msg_data;
-
- const hv_vmbus_channel_open_result *result;
- hv_vmbus_channel_msg_info* msg_info;
- hv_vmbus_channel_msg_header* requestHeader;
- hv_vmbus_channel_open_channel* openMsg;
-
- result = (const hv_vmbus_channel_open_result *)hdr;
-
- /*
- * Find the open msg, copy the result and signal/unblock the wait event
- */
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
-
- TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
- msg_list_entry) {
- requestHeader = (hv_vmbus_channel_msg_header*) msg_info->msg;
-
- if (requestHeader->message_type ==
- HV_CHANNEL_MESSAGE_OPEN_CHANNEL) {
- openMsg = (hv_vmbus_channel_open_channel*) msg_info->msg;
- if (openMsg->child_rel_id == result->child_rel_id
- && openMsg->open_id == result->open_id) {
- memcpy(&msg_info->response.open_result, result,
- sizeof(hv_vmbus_channel_open_result));
- sema_post(&msg_info->wait_sema);
- break;
- }
- }
- }
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
-
+ vmbus_msghc_wakeup(sc, msg);
}
/**
@@ -474,39 +441,7 @@ static void
vmbus_channel_on_gpadl_created(struct vmbus_softc *sc,
const struct vmbus_message *msg)
{
- const hv_vmbus_channel_msg_header *hdr =
- (const hv_vmbus_channel_msg_header *)msg->msg_data;
-
- const hv_vmbus_channel_gpadl_created *gpadl_created;
- hv_vmbus_channel_msg_info* msg_info;
- hv_vmbus_channel_msg_header* request_header;
- hv_vmbus_channel_gpadl_header* gpadl_header;
-
- gpadl_created = (const hv_vmbus_channel_gpadl_created *)hdr;
-
- /* Find the establish msg, copy the result and signal/unblock
- * the wait event
- */
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
- TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
- msg_list_entry) {
- request_header = (hv_vmbus_channel_msg_header*) msg_info->msg;
- if (request_header->message_type ==
- HV_CHANNEL_MESSAGEL_GPADL_HEADER) {
- gpadl_header =
- (hv_vmbus_channel_gpadl_header*) request_header;
-
- if ((gpadl_created->child_rel_id == gpadl_header->child_rel_id)
- && (gpadl_created->gpadl == gpadl_header->gpadl)) {
- memcpy(&msg_info->response.gpadl_created,
- gpadl_created,
- sizeof(hv_vmbus_channel_gpadl_created));
- sema_post(&msg_info->wait_sema);
- break;
- }
- }
- }
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
+ vmbus_msghc_wakeup(sc, msg);
}
/**
@@ -520,42 +455,7 @@ static void
vmbus_channel_on_gpadl_torndown(struct vmbus_softc *sc,
const struct vmbus_message *msg)
{
- const hv_vmbus_channel_msg_header *hdr =
- (const hv_vmbus_channel_msg_header *)msg->msg_data;
-
- const hv_vmbus_channel_gpadl_torndown *gpadl_torndown;
- hv_vmbus_channel_msg_info* msg_info;
- hv_vmbus_channel_msg_header* requestHeader;
- hv_vmbus_channel_gpadl_teardown* gpadlTeardown;
-
- gpadl_torndown = (const hv_vmbus_channel_gpadl_torndown *)hdr;
-
- /*
- * Find the open msg, copy the result and signal/unblock the
- * wait event.
- */
-
- mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
-
- TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
- msg_list_entry) {
- requestHeader = (hv_vmbus_channel_msg_header*) msg_info->msg;
-
- if (requestHeader->message_type
- == HV_CHANNEL_MESSAGE_GPADL_TEARDOWN) {
- gpadlTeardown =
- (hv_vmbus_channel_gpadl_teardown*) requestHeader;
-
- if (gpadl_torndown->gpadl == gpadlTeardown->gpadl) {
- memcpy(&msg_info->response.gpadl_torndown,
- gpadl_torndown,
- sizeof(hv_vmbus_channel_gpadl_torndown));
- sema_post(&msg_info->wait_sema);
- break;
- }
- }
- }
- mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
+ vmbus_msghc_wakeup(sc, msg);
}
static void
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index a706c95..21e48e6 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -73,10 +73,6 @@ hv_vmbus_connect(struct vmbus_softc *sc)
*/
hv_vmbus_g_connection.connect_state = HV_CONNECTING;
- TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor);
- mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg",
- NULL, MTX_DEF);
-
TAILQ_INIT(&hv_vmbus_g_connection.channel_anchor);
mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel",
NULL, MTX_DEF);
@@ -96,8 +92,6 @@ int
hv_vmbus_disconnect(void)
{
- mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
-
free(hv_vmbus_g_connection.channels, M_DEVBUF);
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
@@ -168,40 +162,6 @@ vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu)
}
/**
- * Send a msg on the vmbus's message connection
- */
-int hv_vmbus_post_message(void *buffer, size_t bufferLen)
-{
- hv_vmbus_connection_id connId;
- sbintime_t time = SBT_1MS;
- int retries;
- int ret;
-
- connId.as_uint32_t = 0;
- connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
-
- /*
- * We retry to cope with transient failures caused by host side's
- * insufficient resources. 20 times should suffice in practice.
- */
- for (retries = 0; retries < 20; retries++) {
- ret = hv_vmbus_post_msg_via_msg_ipc(connId,
- HYPERV_MSGTYPE_CHANNEL, buffer, bufferLen);
- if (ret == HV_STATUS_SUCCESS)
- return (0);
-
- pause_sbt("pstmsg", time, 0, C_HARDCLOCK);
- if (time < SBT_1S * 2)
- time *= 2;
- }
-
- KASSERT(ret == HV_STATUS_SUCCESS,
- ("Error VMBUS: Message Post Failed, ret=%d\n", ret));
-
- return (EAGAIN);
-}
-
-/**
* Send an event notification to the parent
*/
int
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 3de7e8d..5e5a15c 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -90,47 +90,6 @@ typedef struct {
hv_vmbus_ring_buffer_debug_info outbound;
} hv_vmbus_channel_debug_info;
-typedef union {
- hv_vmbus_channel_version_supported version_supported;
- hv_vmbus_channel_open_result open_result;
- hv_vmbus_channel_gpadl_torndown gpadl_torndown;
- hv_vmbus_channel_gpadl_created gpadl_created;
-} hv_vmbus_channel_msg_response;
-
-/*
- * Represents each channel msg on the vmbus connection
- * This is a variable-size data structure depending on
- * the msg type itself
- */
-typedef struct hv_vmbus_channel_msg_info {
- /*
- * Bookkeeping stuff
- */
- TAILQ_ENTRY(hv_vmbus_channel_msg_info) msg_list_entry;
- /*
- * So far, this is only used to handle
- * gpadl body message
- */
- TAILQ_HEAD(, hv_vmbus_channel_msg_info) sub_msg_list_anchor;
- /*
- * Synchronize the request/response if
- * needed.
- * KYS: Use a semaphore for now.
- * Not perf critical.
- */
- struct sema wait_sema;
- hv_vmbus_channel_msg_response response;
- uint32_t message_size;
- /**
- * The channel message that goes out on
- * the "wire". It will contain at
- * minimum the
- * hv_vmbus_channel_msg_header
- * header.
- */
- unsigned char msg[0];
-} hv_vmbus_channel_msg_info;
-
/*
* The format must be the same as hv_vm_data_gpa_direct
*/
@@ -244,8 +203,6 @@ typedef struct {
hv_vmbus_connect_state connect_state;
uint32_t next_gpadl_handle;
- TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor;
- struct mtx channel_msg_lock;
/**
* List of primary channels. Sub channels will be linked
* under their primary channel.
@@ -321,17 +278,6 @@ typedef struct {
} hv_vmbus_monitor_page;
/*
- * Define the hv_vmbus_post_message hypercall input structure
- */
-typedef struct {
- hv_vmbus_connection_id connection_id;
- uint32_t reserved;
- hv_vmbus_msg_type message_type;
- uint32_t payload_size;
- uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
-} hv_vmbus_input_post_message;
-
-/*
* Declare the various hypercall operations
*/
typedef enum {
@@ -398,12 +344,6 @@ uint32_t hv_ring_buffer_read_end(
void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel);
void hv_vmbus_release_unattached_channels(void);
-uint16_t hv_vmbus_post_msg_via_msg_ipc(
- hv_vmbus_connection_id connection_id,
- hv_vmbus_msg_type message_type,
- void *payload,
- size_t payload_size);
-
uint16_t hv_vmbus_signal_event(void *con_id);
struct hv_device* hv_vmbus_child_device_create(
@@ -423,7 +363,6 @@ int hv_vmbus_child_device_unregister(
*/
int hv_vmbus_connect(struct vmbus_softc *);
int hv_vmbus_disconnect(void);
-int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(hv_vmbus_channel *channel);
#endif /* __HYPERV_PRIV_H__ */
diff --git a/sys/dev/hyperv/vmbus/hyperv.c b/sys/dev/hyperv/vmbus/hyperv.c
index 0ce033f..94ef5fa 100644
--- a/sys/dev/hyperv/vmbus/hyperv.c
+++ b/sys/dev/hyperv/vmbus/hyperv.c
@@ -126,51 +126,6 @@ hypercall_post_message(bus_addr_t msg_paddr)
}
/**
- * @brief Post a message using the hypervisor message IPC.
- * (This involves a hypercall.)
- */
-hv_vmbus_status
-hv_vmbus_post_msg_via_msg_ipc(
- hv_vmbus_connection_id connection_id,
- hv_vmbus_msg_type message_type,
- void* payload,
- size_t payload_size)
-{
- struct alignedinput {
- uint64_t alignment8;
- hv_vmbus_input_post_message msg;
- };
-
- hv_vmbus_input_post_message* aligned_msg;
- hv_vmbus_status status;
- size_t addr;
-
- if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
- return (EMSGSIZE);
-
- addr = (size_t) malloc(sizeof(struct alignedinput), M_DEVBUF,
- M_ZERO | M_NOWAIT);
- KASSERT(addr != 0,
- ("Error VMBUS: malloc failed to allocate message buffer!"));
- if (addr == 0)
- return (ENOMEM);
-
- aligned_msg = (hv_vmbus_input_post_message*)
- (HV_ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN));
-
- aligned_msg->connection_id = connection_id;
- aligned_msg->message_type = message_type;
- aligned_msg->payload_size = payload_size;
- memcpy((void*) aligned_msg->payload, payload, payload_size);
-
- status = hv_vmbus_do_hypercall(
- HV_CALL_POST_MESSAGE, aligned_msg, 0) & 0xFFFF;
-
- free((void *) addr, M_DEVBUF);
- return (status);
-}
-
-/**
* @brief Signal an event on the specified connection using the hypervisor
* event IPC. (This involves a hypercall.)
*/
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index 6a3999d..d7a9b5d 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -205,25 +205,34 @@ vmbus_msghc_get1(struct vmbus_msghc_ctx *mhc, uint32_t dtor_flag)
return mh;
}
-struct vmbus_msghc *
-vmbus_msghc_get(struct vmbus_softc *sc, size_t dsize)
+void
+vmbus_msghc_reset(struct vmbus_msghc *mh, size_t dsize)
{
struct hypercall_postmsg_in *inprm;
- struct vmbus_msghc *mh;
if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
- return NULL;
-
- mh = vmbus_msghc_get1(sc->vmbus_msg_hc, VMBUS_MSGHC_CTXF_DESTROY);
- if (mh == NULL)
- return NULL;
+ panic("invalid data size %zu", dsize);
inprm = mh->mh_inprm;
memset(inprm, 0, HYPERCALL_POSTMSGIN_SIZE);
inprm->hc_connid = VMBUS_CONNID_MESSAGE;
inprm->hc_msgtype = HYPERV_MSGTYPE_CHANNEL;
inprm->hc_dsize = dsize;
+}
+
+struct vmbus_msghc *
+vmbus_msghc_get(struct vmbus_softc *sc, size_t dsize)
+{
+ struct vmbus_msghc *mh;
+
+ if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
+ panic("invalid data size %zu", dsize);
+
+ mh = vmbus_msghc_get1(sc->vmbus_msg_hc, VMBUS_MSGHC_CTXF_DESTROY);
+ if (mh == NULL)
+ return NULL;
+ vmbus_msghc_reset(mh, dsize);
return mh;
}
diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h
index 04545bf..767879e 100644
--- a/sys/dev/hyperv/vmbus/vmbus_reg.h
+++ b/sys/dev/hyperv/vmbus/vmbus_reg.h
@@ -30,6 +30,7 @@
#define _VMBUS_REG_H_
#include <sys/param.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
/*
* Hyper-V SynIC message format.
@@ -78,12 +79,29 @@ CTASSERT(sizeof(struct vmbus_evtflags) == VMBUS_EVTFLAGS_SIZE);
#define VMBUS_CHAN_MAX (VMBUS_EVTFLAG_LEN * VMBUS_EVTFLAGS_MAX)
/*
+ * GPA range.
+ */
+struct vmbus_gpa_range {
+ uint32_t gpa_len;
+ uint32_t gpa_ofs;
+ uint64_t gpa_page[];
+} __packed;
+
+/*
* Channel messages
* - Embedded in vmbus_message.msg_data, e.g. response.
* - Embedded in hypercall_postmsg_in.hc_data, e.g. request.
*/
#define VMBUS_CHANMSG_TYPE_CHANNEL_REQ 3 /* REQ */
+#define VMBUS_CHANMSG_TYPE_CHOPEN 5 /* REQ */
+#define VMBUS_CHANMSG_TYPE_CHOPEN_RESP 6 /* RESP */
+#define VMBUS_CHANMSG_TYPE_CHCLOSE 7 /* REQ */
+#define VMBUS_CHANMSG_TYPE_GPADL_CONN 8 /* REQ */
+#define VMBUS_CHANMSG_TYPE_GPADL_SUBCONN 9 /* REQ */
+#define VMBUS_CHANMSG_TYPE_GPADL_CONNRESP 10 /* RESP */
+#define VMBUS_CHANMSG_TYPE_GPADL_DISCONN 11 /* REQ */
+#define VMBUS_CHANMSG_TYPE_GPADL_DISCONNRESP 12 /* RESP */
#define VMBUS_CHANMSG_TYPE_INIT_CONTACT 14 /* REQ */
#define VMBUS_CHANMSG_TYPE_VERSION_RESP 15 /* RESP */
#define VMBUS_CHANMSG_TYPE_UNLOAD 16 /* REQ */
@@ -119,4 +137,73 @@ struct vmbus_chanmsg_unload {
struct vmbus_chanmsg_hdr chm_hdr;
} __packed;
+/* VMBUS_CHANMSG_TYPE_CHOPEN */
+struct vmbus_chanmsg_chopen {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_openid;
+ uint32_t chm_gpadl;
+ uint32_t chm_vcpuid;
+ uint32_t chm_rxbr_pgofs;
+#define VMBUS_CHANMSG_CHOPEN_UDATA_SIZE 120
+ uint8_t chm_udata[VMBUS_CHANMSG_CHOPEN_UDATA_SIZE];
+} __packed;
+
+/* VMBUS_CHANMSG_TYPE_CHOPEN_RESP */
+struct vmbus_chanmsg_chopen_resp {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_openid;
+ uint32_t chm_status;
+} __packed;
+
+/* VMBUS_CHANMSG_TYPE_GPADL_CONN */
+struct vmbus_chanmsg_gpadl_conn {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_gpadl;
+ uint16_t chm_range_len;
+ uint16_t chm_range_cnt;
+ struct vmbus_gpa_range chm_range;
+} __packed;
+
+#define VMBUS_CHANMSG_GPADL_CONN_PGMAX 26
+CTASSERT(__offsetof(struct vmbus_chanmsg_gpadl_conn,
+ chm_range.gpa_page[VMBUS_CHANMSG_GPADL_CONN_PGMAX]) <=
+ HYPERCALL_POSTMSGIN_DSIZE_MAX);
+
+/* VMBUS_CHANMSG_TYPE_GPADL_SUBCONN */
+struct vmbus_chanmsg_gpadl_subconn {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_msgno;
+ uint32_t chm_gpadl;
+ uint64_t chm_gpa_page[];
+} __packed;
+
+#define VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX 28
+CTASSERT(__offsetof(struct vmbus_chanmsg_gpadl_subconn,
+ chm_gpa_page[VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX]) <=
+ HYPERCALL_POSTMSGIN_DSIZE_MAX);
+
+/* VMBUS_CHANMSG_TYPE_GPADL_CONNRESP */
+struct vmbus_chanmsg_gpadl_connresp {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_gpadl;
+ uint32_t chm_status;
+} __packed;
+
+/* VMBUS_CHANMSG_TYPE_CHCLOSE */
+struct vmbus_chanmsg_chclose {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+} __packed;
+
+/* VMBUS_CHANMSG_TYPE_GPADL_DISCONN */
+struct vmbus_chanmsg_gpadl_disconn {
+ struct vmbus_chanmsg_hdr chm_hdr;
+ uint32_t chm_chanid;
+ uint32_t chm_gpadl;
+} __packed;
+
#endif /* !_VMBUS_REG_H_ */
diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h
index 37ecea8..df78d86 100644
--- a/sys/dev/hyperv/vmbus/vmbus_var.h
+++ b/sys/dev/hyperv/vmbus/vmbus_var.h
@@ -132,6 +132,7 @@ int vmbus_msghc_exec(struct vmbus_softc *, struct vmbus_msghc *);
const struct vmbus_message *vmbus_msghc_wait_result(struct vmbus_softc *,
struct vmbus_msghc *);
void vmbus_msghc_wakeup(struct vmbus_softc *, const struct vmbus_message *);
+void vmbus_msghc_reset(struct vmbus_msghc *, size_t);
void vmbus_scan_done(struct vmbus_softc *);
void vmbus_scan_newchan(struct vmbus_softc *);
OpenPOWER on IntegriCloud