diff options
-rw-r--r-- | sys/dev/hyperv/include/hyperv.h | 168 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel.c | 580 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel_mgmt.c | 108 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_connection.c | 40 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 61 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hyperv.c | 45 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus.c | 25 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_reg.h | 87 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_var.h | 1 |
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 *); |