diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/hyperv/include/hyperv.h | 63 | ||||
-rw-r--r-- | sys/dev/hyperv/include/vmbus.h | 69 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_net_vsc.c | 38 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_net_vsc.h | 7 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 20 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_rndis_filter.c | 32 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_rndis_filter.h | 1 | ||||
-rw-r--r-- | sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c | 95 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_heartbeat.c | 3 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_kvp.c | 2 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_shutdown.c | 3 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_timesync.c | 3 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel.c | 281 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 28 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_reg.h | 37 |
15 files changed, 308 insertions, 374 deletions
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 9b59e20..7032794 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -82,19 +82,6 @@ typedef uint8_t hv_bool_uint8_t; #define VMBUS_VERSION_MAJOR(ver) (((uint32_t)(ver)) >> 16) #define VMBUS_VERSION_MINOR(ver) (((uint32_t)(ver)) & 0xffff) -#define HV_MAX_PAGE_BUFFER_COUNT 32 -#define HV_MAX_MULTIPAGE_BUFFER_COUNT 32 - -#define HV_ALIGN_UP(value, align) \ - (((value) & (align-1)) ? \ - (((value) + (align-1)) & ~(align-1) ) : (value)) - -#define HV_ALIGN_DOWN(value, align) ( (value) & ~(align-1) ) - -#define HV_NUM_PAGES_SPANNED(addr, len) \ - ((HV_ALIGN_UP(addr+len, PAGE_SIZE) - \ - HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT ) - struct hyperv_guid { uint8_t hv_guid[16]; } __packed; @@ -125,25 +112,6 @@ typedef struct { hv_vm_transfer_page ranges[1]; } __packed hv_vm_transfer_page_packet_header; -typedef enum { - HV_VMBUS_PACKET_TYPE_INVALID = 0x0, - HV_VMBUS_PACKET_TYPES_SYNCH = 0x1, - HV_VMBUS_PACKET_TYPE_ADD_TRANSFER_PAGE_SET = 0x2, - HV_VMBUS_PACKET_TYPE_REMOVE_TRANSFER_PAGE_SET = 0x3, - HV_VMBUS_PACKET_TYPE_ESTABLISH_GPADL = 0x4, - HV_VMBUS_PACKET_TYPE_TEAR_DOWN_GPADL = 0x5, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND = 0x6, - HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES = 0x7, - HV_VMBUS_PACKET_TYPE_DATA_USING_GPADL = 0x8, - HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT = 0x9, - HV_VMBUS_PACKET_TYPE_CANCEL_REQUEST = 0xa, - HV_VMBUS_PACKET_TYPE_COMPLETION = 0xb, - HV_VMBUS_PACKET_TYPE_DATA_USING_ADDITIONAL_PACKETS = 0xc, - HV_VMBUS_PACKET_TYPE_ADDITIONAL_DATA = 0xd -} hv_vmbus_packet_type; - -#define HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED 1 - #define HW_MACADDR_LEN 6 /* @@ -225,18 +193,6 @@ typedef struct { } __packed hv_vmbus_ring_buffer; typedef struct { - int length; - int offset; - uint64_t pfn; -} __packed hv_vmbus_page_buffer; - -typedef struct { - int length; - int offset; - uint64_t pfn_array[HV_MAX_MULTIPAGE_BUFFER_COUNT]; -} __packed hv_vmbus_multipage_buffer; - -typedef struct { hv_vmbus_ring_buffer* ring_buffer; struct mtx ring_lock; uint32_t ring_data_size; /* ring_size */ @@ -372,23 +328,8 @@ int hv_vmbus_channel_send_packet( void* buffer, uint32_t buffer_len, uint64_t request_id, - hv_vmbus_packet_type type, - uint32_t flags); - -int hv_vmbus_channel_send_packet_pagebuffer( - hv_vmbus_channel* channel, - hv_vmbus_page_buffer page_buffers[], - uint32_t page_count, - void* buffer, - uint32_t buffer_len, - uint64_t request_id); - -int hv_vmbus_channel_send_packet_multipagebuffer( - hv_vmbus_channel* channel, - hv_vmbus_multipage_buffer* multi_page_buffer, - void* buffer, - uint32_t buffer_len, - uint64_t request_id); + uint16_t type, + uint16_t flags); int hv_vmbus_channel_establish_gpadl( hv_vmbus_channel* channel, diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h new file mode 100644 index 0000000..1960e84 --- /dev/null +++ b/sys/dev/hyperv/include/vmbus.h @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _VMBUS_H_ +#define _VMBUS_H_ + +#include <sys/param.h> + +/* + * GPA stuffs. + */ +struct vmbus_gpa_range { + uint32_t gpa_len; + uint32_t gpa_ofs; + uint64_t gpa_page[0]; +} __packed; + +/* This is actually vmbus_gpa_range.gpa_page[1] */ +struct vmbus_gpa { + uint32_t gpa_len; + uint32_t gpa_ofs; + uint64_t gpa_page; +} __packed; + +#define VMBUS_CHANPKT_TYPE_INBAND 0x0006 +#define VMBUS_CHANPKT_TYPE_RXBUF 0x0007 +#define VMBUS_CHANPKT_TYPE_GPA 0x0009 +#define VMBUS_CHANPKT_TYPE_COMP 0x000b + +#define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */ + +#define VMBUS_CHAN_SGLIST_MAX 32 +#define VMBUS_CHAN_PRPLIST_MAX 32 + +struct hv_vmbus_channel; + +int vmbus_chan_send_sglist(struct hv_vmbus_channel *chan, + struct vmbus_gpa sg[], int sglen, void *data, int dlen, + uint64_t xactid); +int vmbus_chan_send_prplist(struct hv_vmbus_channel *chan, + struct vmbus_gpa_range *prp, int prp_cnt, void *data, int dlen, + uint64_t xactid); + +#endif /* !_VMBUS_H_ */ diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 6f8b98d..0ba7ee2 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -185,8 +185,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC); if (ret != 0) { goto cleanup; } @@ -279,8 +278,7 @@ hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt, sizeof(nvsp_msg), (uint64_t)init_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC); if (ret != 0) { goto cleanup; } @@ -340,7 +338,7 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_dev) ret = hv_vmbus_channel_send_packet(net_dev->sc->hn_prichan, revoke_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)revoke_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); /* * If we failed here, we might as well return and have a leak @@ -408,7 +406,7 @@ hv_nv_destroy_send_buffer(netvsc_dev *net_dev) ret = hv_vmbus_channel_send_packet(net_dev->sc->hn_prichan, revoke_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)revoke_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); /* * If we failed here, we might as well return and have a leak * rather than continue and a bugchk @@ -474,8 +472,7 @@ hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, /* Send the init request */ ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC); if (ret != 0) return (-1); @@ -518,7 +515,7 @@ hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) /* Send the configuration packet */ ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); if (ret != 0) return (-EINVAL); @@ -597,15 +594,14 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); if (ret != 0) { goto cleanup; } /* * TODO: BUGBUG - We have to wait for the above msg since the netvsp * uses KMCL which acknowledges packet (completion packet) - * since our Vmbus always set the - * HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag + * since our Vmbus always set the VMBUS_CHANPKT_FLAG_RC flag */ /* sema_wait(&NetVscChannel->channel_init_sema); */ @@ -816,15 +812,13 @@ hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt) send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = pkt->send_buf_section_size; - if (pkt->page_buf_count) { - ret = hv_vmbus_channel_send_packet_pagebuffer(chan, - pkt->page_buffers, pkt->page_buf_count, + if (pkt->gpa_cnt) { + ret = vmbus_chan_send_sglist(chan, pkt->gpa, pkt->gpa_cnt, &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt); } else { ret = hv_vmbus_channel_send_packet(chan, &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC); } return (ret); @@ -853,7 +847,7 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, * All inbound packets other than send completion should be * xfer page packet. */ - if (pkt->type != HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES) { + if (pkt->type != VMBUS_CHANPKT_TYPE_RXBUF) { device_printf(dev, "packet type %d is invalid!\n", pkt->type); return; } @@ -924,7 +918,7 @@ hv_nv_on_receive_completion(struct hv_vmbus_channel *chan, uint64_t tid, retry_send_cmplt: /* Send the completion */ ret = hv_vmbus_channel_send_packet(chan, &rx_comp_msg, - sizeof(nvsp_msg), tid, HV_VMBUS_PACKET_TYPE_COMPLETION, 0); + sizeof(nvsp_msg), tid, VMBUS_CHANPKT_TYPE_COMP, 0); if (ret == 0) { /* success */ /* no-op */ @@ -1009,14 +1003,14 @@ hv_nv_on_channel_callback(void *xchan) if (bytes_rxed > 0) { desc = (hv_vm_packet_descriptor *)buffer; switch (desc->type) { - case HV_VMBUS_PACKET_TYPE_COMPLETION: + case VMBUS_CHANPKT_TYPE_COMP: hv_nv_on_send_completion(net_dev, chan, desc); break; - case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES: + case VMBUS_CHANPKT_TYPE_RXBUF: hv_nv_on_receive(net_dev, sc, chan, desc); break; - case HV_VMBUS_PACKET_TYPE_DATA_IN_BAND: + case VMBUS_CHANPKT_TYPE_INBAND: hv_nv_send_table(sc, desc); break; default: diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index e162c67..c9bce0f 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -57,6 +57,7 @@ #include <net/if_media.h> #include <dev/hyperv/include/hyperv.h> +#include <dev/hyperv/include/vmbus.h> #define HN_USE_TXDESC_BUFRING @@ -1082,8 +1083,6 @@ struct hv_vmbus_channel; typedef void (*pfn_on_send_rx_completion)(struct hv_vmbus_channel *, void *); #define NETVSC_DEVICE_RING_BUFFER_SIZE (128 * PAGE_SIZE) -#define NETVSC_PACKET_MAXPAGE 32 - #define NETVSC_VLAN_PRIO_MASK 0xe000 #define NETVSC_VLAN_PRIO_SHIFT 13 @@ -1132,8 +1131,8 @@ typedef struct netvsc_packet_ { void *rndis_mesg; uint32_t tot_data_buf_len; void *data; - uint32_t page_buf_count; - hv_vmbus_page_buffer page_buffers[NETVSC_PACKET_MAXPAGE]; + uint32_t gpa_cnt; + struct vmbus_gpa gpa[VMBUS_CHAN_SGLIST_MAX]; } netvsc_packet; typedef struct { diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 0f774cd..8ff45bc 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -154,7 +154,7 @@ __FBSDID("$FreeBSD$"); #define HN_TX_DATA_MAXSIZE IP_MAXPACKET #define HN_TX_DATA_SEGSIZE PAGE_SIZE #define HN_TX_DATA_SEGCNT_MAX \ - (NETVSC_PACKET_MAXPAGE - HV_RF_NUM_TX_RESERVED_PAGE_BUFS) + (VMBUS_CHAN_SGLIST_MAX - HV_RF_NUM_TX_RESERVED_PAGE_BUFS) #define HN_DIRECT_TX_SIZE_DEF 128 @@ -998,7 +998,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) packet->send_buf_section_idx = send_buf_section_idx; packet->send_buf_section_size = packet->tot_data_buf_len; - packet->page_buf_count = 0; + packet->gpa_cnt = 0; txr->hn_tx_chimney++; goto done; } @@ -1024,24 +1024,24 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) } *m_head0 = m_head; - packet->page_buf_count = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS; + packet->gpa_cnt = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS; /* send packet with page buffer */ - packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr); - packet->page_buffers[0].offset = txd->rndis_msg_paddr & PAGE_MASK; - packet->page_buffers[0].length = rndis_msg_size; + packet->gpa[0].gpa_page = atop(txd->rndis_msg_paddr); + packet->gpa[0].gpa_ofs = txd->rndis_msg_paddr & PAGE_MASK; + packet->gpa[0].gpa_len = rndis_msg_size; /* * Fill the page buffers with mbuf info starting at index * HV_RF_NUM_TX_RESERVED_PAGE_BUFS. */ for (i = 0; i < nsegs; ++i) { - hv_vmbus_page_buffer *pb = &packet->page_buffers[ + struct vmbus_gpa *gpa = &packet->gpa[ i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; - pb->pfn = atop(segs[i].ds_addr); - pb->offset = segs[i].ds_addr & PAGE_MASK; - pb->length = segs[i].ds_len; + gpa->gpa_page = atop(segs[i].ds_addr); + gpa->gpa_ofs = segs[i].ds_addr & PAGE_MASK; + gpa->gpa_len = segs[i].ds_len; } packet->send_buf_section_idx = diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index cbae5fb..9a6a025 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -248,26 +248,23 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, packet->is_data_pkt = FALSE; packet->tot_data_buf_len = request->request_msg.msg_len; - packet->page_buf_count = 1; + packet->gpa_cnt = 1; - packet->page_buffers[0].pfn = + packet->gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT; - packet->page_buffers[0].length = request->request_msg.msg_len; - packet->page_buffers[0].offset = + packet->gpa[0].gpa_len = request->request_msg.msg_len; + packet->gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1); - if (packet->page_buffers[0].offset + - packet->page_buffers[0].length > PAGE_SIZE) { - packet->page_buf_count = 2; - packet->page_buffers[0].length = - PAGE_SIZE - packet->page_buffers[0].offset; - packet->page_buffers[1].pfn = + if (packet->gpa[0].gpa_ofs + packet->gpa[0].gpa_len > PAGE_SIZE) { + packet->gpa_cnt = 2; + packet->gpa[0].gpa_len = PAGE_SIZE - packet->gpa[0].gpa_ofs; + packet->gpa[1].gpa_page = hv_get_phys_addr((char*)&request->request_msg + - packet->page_buffers[0].length) >> PAGE_SHIFT; - packet->page_buffers[1].offset = 0; - packet->page_buffers[1].length = - request->request_msg.msg_len - - packet->page_buffers[0].length; + packet->gpa[0].gpa_len) >> PAGE_SHIFT; + packet->gpa[1].gpa_ofs = 0; + packet->gpa[1].gpa_len = request->request_msg.msg_len - + packet->gpa[0].gpa_len; } packet->compl.send.send_completion_context = request; /* packet */ @@ -289,7 +286,7 @@ hv_rf_send_request(rndis_device *device, rndis_request *request, memcpy(dest, &request->request_msg, request->request_msg.msg_len); packet->send_buf_section_idx = send_buf_section_idx; packet->send_buf_section_size = packet->tot_data_buf_len; - packet->page_buf_count = 0; + packet->gpa_cnt = 0; goto sendit; } /* Failed to allocate chimney send buffer; move on */ @@ -1171,8 +1168,7 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC); if (ret != 0) { device_printf(dev, "Fail to allocate subchannel\n"); goto out; diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.h b/sys/dev/hyperv/netvsc/hv_rndis_filter.h index 2d97a09..20e5f27 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.h +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.h @@ -74,7 +74,6 @@ typedef struct rndis_request_ { /* Simplify allocation by having a netvsc packet inline */ netvsc_packet pkt; - hv_vmbus_page_buffer buffer; /* * The max request size is sizeof(rndis_msg) + PAGE_SIZE. diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index a184480..5f3638c 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include <cam/scsi/scsi_message.h> #include <dev/hyperv/include/hyperv.h> +#include <dev/hyperv/include/vmbus.h> #include "hv_vstorage.h" #include "vmbus_if.h" @@ -100,7 +101,7 @@ struct hv_sgl_page_pool{ boolean_t is_init; } g_hv_sgl_page_pool; -#define STORVSC_MAX_SG_PAGE_CNT STORVSC_MAX_IO_REQUESTS * HV_MAX_MULTIPAGE_BUFFER_COUNT +#define STORVSC_MAX_SG_PAGE_CNT STORVSC_MAX_IO_REQUESTS * VMBUS_CHAN_PRPLIST_MAX enum storvsc_request_type { WRITE_TYPE, @@ -108,10 +109,16 @@ enum storvsc_request_type { UNKNOWN_TYPE }; +struct hvs_gpa_range { + struct vmbus_gpa_range gpa_range; + uint64_t gpa_page[VMBUS_CHAN_PRPLIST_MAX]; +} __packed; + struct hv_storvsc_request { LIST_ENTRY(hv_storvsc_request) link; struct vstor_packet vstor_packet; - hv_vmbus_multipage_buffer data_buf; + int prp_cnt; + struct hvs_gpa_range prp_list; void *sense_data; uint8_t sense_info_len; uint8_t retries; @@ -354,8 +361,8 @@ storvsc_send_multichannel_request(struct storvsc_softc *sc, int max_chans) vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); /* wait for 5 seconds */ ret = sema_timedwait(&request->synch_sema, 5 * hz); @@ -425,8 +432,8 @@ hv_storvsc_channel_init(struct storvsc_softc *sc) vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); if (ret != 0) goto cleanup; @@ -459,8 +466,8 @@ hv_storvsc_channel_init(struct storvsc_softc *sc) vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); if (ret != 0) goto cleanup; @@ -502,8 +509,8 @@ hv_storvsc_channel_init(struct storvsc_softc *sc) vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); if ( ret != 0) goto cleanup; @@ -538,8 +545,8 @@ hv_storvsc_channel_init(struct storvsc_softc *sc) vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); if (ret != 0) { goto cleanup; @@ -628,8 +635,8 @@ hv_storvsc_host_reset(struct storvsc_softc *sc) vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)&sc->hs_reset_req, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); if (ret != 0) { goto cleanup; @@ -675,29 +682,26 @@ hv_storvsc_io_request(struct storvsc_softc *sc, vstor_packet->u.vm_srb.sense_info_len = sense_buffer_size; - vstor_packet->u.vm_srb.transfer_len = request->data_buf.length; + vstor_packet->u.vm_srb.transfer_len = + request->prp_list.gpa_range.gpa_len; vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB; outgoing_channel = vmbus_select_outgoing_channel(sc->hs_chan); mtx_unlock(&request->softc->hs_lock); - if (request->data_buf.length) { - ret = hv_vmbus_channel_send_packet_multipagebuffer( - outgoing_channel, - &request->data_buf, - vstor_packet, - VSTOR_PKT_SIZE, - (uint64_t)(uintptr_t)request); - + if (request->prp_list.gpa_range.gpa_len) { + ret = vmbus_chan_send_prplist(outgoing_channel, + &request->prp_list.gpa_range, request->prp_cnt, + vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request); } else { ret = hv_vmbus_channel_send_packet( outgoing_channel, vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, - HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC); } mtx_lock(&request->softc->hs_lock); @@ -956,7 +960,7 @@ storvsc_attach(device_t dev) /* * Pre-create SG list, each SG list with - * HV_MAX_MULTIPAGE_BUFFER_COUNT segments, each + * VMBUS_CHAN_PRPLIST_MAX segments, each * segment has one page buffer */ for (i = 0; i < STORVSC_MAX_IO_REQUESTS; i++) { @@ -964,10 +968,10 @@ storvsc_attach(device_t dev) M_DEVBUF, M_WAITOK|M_ZERO); sgl_node->sgl_data = - sglist_alloc(HV_MAX_MULTIPAGE_BUFFER_COUNT, + sglist_alloc(VMBUS_CHAN_PRPLIST_MAX, M_WAITOK|M_ZERO); - for (j = 0; j < HV_MAX_MULTIPAGE_BUFFER_COUNT; j++) { + for (j = 0; j < VMBUS_CHAN_PRPLIST_MAX; j++) { tmp_buff = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK|M_ZERO); @@ -1054,7 +1058,7 @@ cleanup: while (!LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) { sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list); LIST_REMOVE(sgl_node, link); - for (j = 0; j < HV_MAX_MULTIPAGE_BUFFER_COUNT; j++) { + for (j = 0; j < VMBUS_CHAN_PRPLIST_MAX; j++) { if (NULL != (void*)sgl_node->sgl_data->sg_segs[j].ss_paddr) { free((void*)sgl_node->sgl_data->sg_segs[j].ss_paddr, M_DEVBUF); @@ -1117,7 +1121,7 @@ storvsc_detach(device_t dev) while (!LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) { sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list); LIST_REMOVE(sgl_node, link); - for (j = 0; j < HV_MAX_MULTIPAGE_BUFFER_COUNT; j++){ + for (j = 0; j < VMBUS_CHAN_PRPLIST_MAX; j++){ if (NULL != (void*)sgl_node->sgl_data->sg_segs[j].ss_paddr) { free((void*)sgl_node->sgl_data->sg_segs[j].ss_paddr, M_DEVBUF); @@ -1668,6 +1672,7 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp) uint32_t pfn_num = 0; uint32_t pfn; uint64_t not_aligned_seg_bits = 0; + struct hvs_gpa_range *prplist; /* refer to struct vmscsi_req for meanings of these two fields */ reqp->vstor_packet.u.vm_srb.port = @@ -1711,22 +1716,23 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp) return (0); } - reqp->data_buf.length = csio->dxfer_len; + prplist = &reqp->prp_list; + prplist->gpa_range.gpa_len = csio->dxfer_len; switch (ccb->ccb_h.flags & CAM_DATA_MASK) { case CAM_DATA_VADDR: { bytes_to_copy = csio->dxfer_len; phys_addr = vtophys(csio->data_ptr); - reqp->data_buf.offset = phys_addr & PAGE_MASK; + prplist->gpa_range.gpa_ofs = phys_addr & PAGE_MASK; while (bytes_to_copy != 0) { int bytes, page_offset; phys_addr = - vtophys(&csio->data_ptr[reqp->data_buf.length - + vtophys(&csio->data_ptr[prplist->gpa_range.gpa_len - bytes_to_copy]); pfn = phys_addr >> PAGE_SHIFT; - reqp->data_buf.pfn_array[pfn_num] = pfn; + prplist->gpa_page[pfn_num] = pfn; page_offset = phys_addr & PAGE_MASK; bytes = min(PAGE_SIZE - page_offset, bytes_to_copy); @@ -1734,6 +1740,7 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp) bytes_to_copy -= bytes; pfn_num++; } + reqp->prp_cnt = pfn_num; break; } @@ -1750,10 +1757,10 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp) printf("Storvsc: get SG I/O operation, %d\n", reqp->vstor_packet.u.vm_srb.data_in); - if (storvsc_sg_count > HV_MAX_MULTIPAGE_BUFFER_COUNT){ + if (storvsc_sg_count > VMBUS_CHAN_PRPLIST_MAX){ printf("Storvsc: %d segments is too much, " "only support %d segments\n", - storvsc_sg_count, HV_MAX_MULTIPAGE_BUFFER_COUNT); + storvsc_sg_count, VMBUS_CHAN_PRPLIST_MAX); return (EINVAL); } @@ -1806,10 +1813,10 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp) phys_addr = vtophys(storvsc_sglist[0].ds_addr); } - reqp->data_buf.offset = phys_addr & PAGE_MASK; + prplist->gpa_range.gpa_ofs = phys_addr & PAGE_MASK; pfn = phys_addr >> PAGE_SHIFT; - reqp->data_buf.pfn_array[0] = pfn; + prplist->gpa_page[0] = pfn; for (i = 1; i < storvsc_sg_count; i++) { if (reqp->not_aligned_seg_bits & (1 << i)) { @@ -1821,27 +1828,31 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp) } pfn = phys_addr >> PAGE_SHIFT; - reqp->data_buf.pfn_array[i] = pfn; + prplist->gpa_page[i] = pfn; } + reqp->prp_cnt = i; } else { phys_addr = vtophys(storvsc_sglist[0].ds_addr); - reqp->data_buf.offset = phys_addr & PAGE_MASK; + prplist->gpa_range.gpa_ofs = phys_addr & PAGE_MASK; for (i = 0; i < storvsc_sg_count; i++) { phys_addr = vtophys(storvsc_sglist[i].ds_addr); pfn = phys_addr >> PAGE_SHIFT; - reqp->data_buf.pfn_array[i] = pfn; + prplist->gpa_page[i] = pfn; } + reqp->prp_cnt = i; /* check the last segment cross boundary or not */ offset = phys_addr & PAGE_MASK; if (offset) { + /* Add one more PRP entry */ phys_addr = vtophys(storvsc_sglist[i-1].ds_addr + PAGE_SIZE - offset); pfn = phys_addr >> PAGE_SHIFT; - reqp->data_buf.pfn_array[i] = pfn; + prplist->gpa_page[i] = pfn; + reqp->prp_cnt++; } reqp->bounce_sgl_count = 0; diff --git a/sys/dev/hyperv/utilities/hv_heartbeat.c b/sys/dev/hyperv/utilities/hv_heartbeat.c index b8ac7f0e..945d0324 100644 --- a/sys/dev/hyperv/utilities/hv_heartbeat.c +++ b/sys/dev/hyperv/utilities/hv_heartbeat.c @@ -35,6 +35,7 @@ #include <sys/syscallsubr.h> #include <dev/hyperv/include/hyperv.h> +#include <dev/hyperv/include/vmbus.h> #include "hv_util.h" #include "vmbus_if.h" @@ -87,7 +88,7 @@ hv_heartbeat_cb(void *context) HV_ICMSGHDRFLAG_RESPONSE; hv_vmbus_channel_send_packet(channel, buf, recvlen, requestid, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); } } diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index a96d535..98f9268 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -578,7 +578,7 @@ hv_kvp_respond_host(hv_kvp_sc *sc, int error) error = hv_vmbus_channel_send_packet(sc->util_sc.channel, sc->rcv_buf, sc->host_msg_len, sc->host_msg_id, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); if (error) hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n", diff --git a/sys/dev/hyperv/utilities/hv_shutdown.c b/sys/dev/hyperv/utilities/hv_shutdown.c index 949c74b..f70458b 100644 --- a/sys/dev/hyperv/utilities/hv_shutdown.c +++ b/sys/dev/hyperv/utilities/hv_shutdown.c @@ -40,6 +40,7 @@ #include <sys/syscallsubr.h> #include <dev/hyperv/include/hyperv.h> +#include <dev/hyperv/include/vmbus.h> #include "hv_util.h" #include "vmbus_if.h" @@ -106,7 +107,7 @@ hv_shutdown_cb(void *context) hv_vmbus_channel_send_packet(channel, buf, recv_len, request_id, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); } if (execute_shutdown) diff --git a/sys/dev/hyperv/utilities/hv_timesync.c b/sys/dev/hyperv/utilities/hv_timesync.c index 2a11a17..2e29d8f 100644 --- a/sys/dev/hyperv/utilities/hv_timesync.c +++ b/sys/dev/hyperv/utilities/hv_timesync.c @@ -40,6 +40,7 @@ #include <sys/syscallsubr.h> #include <dev/hyperv/include/hyperv.h> +#include <dev/hyperv/include/vmbus.h> #include "hv_util.h" #include "vmbus_if.h" @@ -164,7 +165,7 @@ hv_timesync_cb(void *context) hv_vmbus_channel_send_packet(channel, time_buf, recvlen, requestId, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + VMBUS_CHANPKT_TYPE_INBAND, 0); } } diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index 43da99c..cc78706 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -621,194 +621,119 @@ hv_vmbus_channel_close(struct hv_vmbus_channel *chan) hv_vmbus_channel_close_internal(chan); } -/** - * @brief Send the specified buffer on the given channel - */ int -hv_vmbus_channel_send_packet( - hv_vmbus_channel* channel, - void* buffer, - uint32_t buffer_len, - uint64_t request_id, - hv_vmbus_packet_type type, - uint32_t flags) +hv_vmbus_channel_send_packet(struct hv_vmbus_channel *chan, + void *data, uint32_t dlen, uint64_t xactid, uint16_t type, uint16_t flags) { - int ret = 0; - hv_vm_packet_descriptor desc; - uint32_t packet_len; - uint64_t aligned_data; - uint32_t packet_len_aligned; - boolean_t need_sig; - struct iovec iov[3]; - - packet_len = sizeof(hv_vm_packet_descriptor) + buffer_len; - packet_len_aligned = HV_ALIGN_UP(packet_len, sizeof(uint64_t)); - aligned_data = 0; - - /* Setup the descriptor */ - desc.type = type; /* HV_VMBUS_PACKET_TYPE_DATA_IN_BAND; */ - desc.flags = flags; /* HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED */ - /* in 8-bytes granularity */ - desc.data_offset8 = sizeof(hv_vm_packet_descriptor) >> 3; - desc.length8 = (uint16_t) (packet_len_aligned >> 3); - desc.transaction_id = request_id; - - iov[0].iov_base = &desc; - iov[0].iov_len = sizeof(hv_vm_packet_descriptor); - - iov[1].iov_base = buffer; - iov[1].iov_len = buffer_len; - - iov[2].iov_base = &aligned_data; - iov[2].iov_len = packet_len_aligned - packet_len; - - ret = hv_ring_buffer_write(&channel->outbound, iov, 3, &need_sig); - - /* TODO: We should determine if this is optional */ - if (ret == 0 && need_sig) - vmbus_chan_send_event(channel); - - return (ret); + struct vmbus_chanpkt pkt; + int pktlen, pad_pktlen, hlen, error; + uint64_t pad = 0; + struct iovec iov[3]; + boolean_t send_evt; + + hlen = sizeof(pkt); + pktlen = hlen + dlen; + pad_pktlen = roundup2(pktlen, VMBUS_CHANPKT_SIZE_ALIGN); + + pkt.cp_hdr.cph_type = type; + pkt.cp_hdr.cph_flags = flags; + pkt.cp_hdr.cph_data_ofs = hlen >> VMBUS_CHANPKT_SIZE_SHIFT; + pkt.cp_hdr.cph_len = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT; + pkt.cp_hdr.cph_xactid = xactid; + + iov[0].iov_base = &pkt; + iov[0].iov_len = hlen; + iov[1].iov_base = data; + iov[1].iov_len = dlen; + iov[2].iov_base = &pad; + iov[2].iov_len = pad_pktlen - pktlen; + + error = hv_ring_buffer_write(&chan->outbound, iov, 3, &send_evt); + if (!error && send_evt) + vmbus_chan_send_event(chan); + return error; } -/** - * @brief Send a range of single-page buffer packets using - * a GPADL Direct packet type - */ int -hv_vmbus_channel_send_packet_pagebuffer( - hv_vmbus_channel* channel, - hv_vmbus_page_buffer page_buffers[], - uint32_t page_count, - void* buffer, - uint32_t buffer_len, - uint64_t request_id) +vmbus_chan_send_sglist(struct hv_vmbus_channel *chan, + struct vmbus_gpa sg[], int sglen, void *data, int dlen, uint64_t xactid) { - - int ret = 0; - boolean_t need_sig; - uint32_t packet_len; - uint32_t page_buflen; - uint32_t packetLen_aligned; - struct iovec iov[4]; - hv_vmbus_channel_packet_page_buffer desc; - uint32_t descSize; - uint64_t alignedData = 0; - - if (page_count > HV_MAX_PAGE_BUFFER_COUNT) - return (EINVAL); - - /* - * Adjust the size down since hv_vmbus_channel_packet_page_buffer - * is the largest size we support - */ - descSize = __offsetof(hv_vmbus_channel_packet_page_buffer, range); - page_buflen = sizeof(hv_vmbus_page_buffer) * page_count; - packet_len = descSize + page_buflen + buffer_len; - packetLen_aligned = HV_ALIGN_UP(packet_len, sizeof(uint64_t)); - - /* Setup the descriptor */ - desc.type = HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT; - desc.flags = HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; - /* in 8-bytes granularity */ - desc.data_offset8 = (descSize + page_buflen) >> 3; - desc.length8 = (uint16_t) (packetLen_aligned >> 3); - desc.transaction_id = request_id; - desc.range_count = page_count; - - iov[0].iov_base = &desc; - iov[0].iov_len = descSize; - - iov[1].iov_base = page_buffers; - iov[1].iov_len = page_buflen; - - iov[2].iov_base = buffer; - iov[2].iov_len = buffer_len; - - iov[3].iov_base = &alignedData; - iov[3].iov_len = packetLen_aligned - packet_len; - - ret = hv_ring_buffer_write(&channel->outbound, iov, 4, &need_sig); - - /* TODO: We should determine if this is optional */ - if (ret == 0 && need_sig) - vmbus_chan_send_event(channel); - - return (ret); + struct vmbus_chanpkt_sglist pkt; + int pktlen, pad_pktlen, hlen, error; + struct iovec iov[4]; + boolean_t send_evt; + uint64_t pad = 0; + + KASSERT(sglen < VMBUS_CHAN_SGLIST_MAX, + ("invalid sglist len %d", sglen)); + + hlen = __offsetof(struct vmbus_chanpkt_sglist, cp_gpa[sglen]); + pktlen = hlen + dlen; + pad_pktlen = roundup2(pktlen, VMBUS_CHANPKT_SIZE_ALIGN); + + pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; + pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; + pkt.cp_hdr.cph_data_ofs = hlen >> VMBUS_CHANPKT_SIZE_SHIFT; + pkt.cp_hdr.cph_len = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT; + pkt.cp_hdr.cph_xactid = xactid; + pkt.cp_rsvd = 0; + pkt.cp_gpa_cnt = sglen; + + iov[0].iov_base = &pkt; + iov[0].iov_len = sizeof(pkt); + iov[1].iov_base = sg; + iov[1].iov_len = sizeof(struct vmbus_gpa) * sglen; + iov[2].iov_base = data; + iov[2].iov_len = dlen; + iov[3].iov_base = &pad; + iov[3].iov_len = pad_pktlen - pktlen; + + error = hv_ring_buffer_write(&chan->outbound, iov, 4, &send_evt); + if (!error && send_evt) + vmbus_chan_send_event(chan); + return error; } -/** - * @brief Send a multi-page buffer packet using a GPADL Direct packet type - */ int -hv_vmbus_channel_send_packet_multipagebuffer( - hv_vmbus_channel* channel, - hv_vmbus_multipage_buffer* multi_page_buffer, - void* buffer, - uint32_t buffer_len, - uint64_t request_id) +vmbus_chan_send_prplist(struct hv_vmbus_channel *chan, + struct vmbus_gpa_range *prp, int prp_cnt, void *data, int dlen, + uint64_t xactid) { - - int ret = 0; - uint32_t desc_size; - boolean_t need_sig; - uint32_t packet_len; - uint32_t packet_len_aligned; - uint32_t pfn_count; - uint64_t aligned_data = 0; - struct iovec iov[3]; - hv_vmbus_channel_packet_multipage_buffer desc; - - pfn_count = - HV_NUM_PAGES_SPANNED( - multi_page_buffer->offset, - multi_page_buffer->length); - - if ((pfn_count == 0) || (pfn_count > HV_MAX_MULTIPAGE_BUFFER_COUNT)) - return (EINVAL); - /* - * Adjust the size down since hv_vmbus_channel_packet_multipage_buffer - * is the largest size we support - */ - desc_size = - sizeof(hv_vmbus_channel_packet_multipage_buffer) - - ((HV_MAX_MULTIPAGE_BUFFER_COUNT - pfn_count) * - sizeof(uint64_t)); - packet_len = desc_size + buffer_len; - packet_len_aligned = HV_ALIGN_UP(packet_len, sizeof(uint64_t)); - - /* - * Setup the descriptor - */ - desc.type = HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT; - desc.flags = HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; - desc.data_offset8 = desc_size >> 3; /* in 8-bytes granularity */ - desc.length8 = (uint16_t) (packet_len_aligned >> 3); - desc.transaction_id = request_id; - desc.range_count = 1; - - desc.range.length = multi_page_buffer->length; - desc.range.offset = multi_page_buffer->offset; - - memcpy(desc.range.pfn_array, multi_page_buffer->pfn_array, - pfn_count * sizeof(uint64_t)); - - iov[0].iov_base = &desc; - iov[0].iov_len = desc_size; - - iov[1].iov_base = buffer; - iov[1].iov_len = buffer_len; - - iov[2].iov_base = &aligned_data; - iov[2].iov_len = packet_len_aligned - packet_len; - - ret = hv_ring_buffer_write(&channel->outbound, iov, 3, &need_sig); - - /* TODO: We should determine if this is optional */ - if (ret == 0 && need_sig) - vmbus_chan_send_event(channel); - - return (ret); + struct vmbus_chanpkt_prplist pkt; + int pktlen, pad_pktlen, hlen, error; + struct iovec iov[4]; + boolean_t send_evt; + uint64_t pad = 0; + + KASSERT(prp_cnt < VMBUS_CHAN_PRPLIST_MAX, + ("invalid prplist entry count %d", prp_cnt)); + + hlen = __offsetof(struct vmbus_chanpkt_prplist, + cp_range[0].gpa_page[prp_cnt]); + pktlen = hlen + dlen; + pad_pktlen = roundup2(pktlen, VMBUS_CHANPKT_SIZE_ALIGN); + + pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; + pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; + pkt.cp_hdr.cph_data_ofs = hlen >> VMBUS_CHANPKT_SIZE_SHIFT; + pkt.cp_hdr.cph_len = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT; + pkt.cp_hdr.cph_xactid = xactid; + pkt.cp_rsvd = 0; + pkt.cp_range_cnt = 1; + + iov[0].iov_base = &pkt; + iov[0].iov_len = sizeof(pkt); + iov[1].iov_base = prp; + iov[1].iov_len = __offsetof(struct vmbus_gpa_range, gpa_page[prp_cnt]); + iov[2].iov_base = data; + iov[2].iov_len = dlen; + iov[3].iov_base = &pad; + iov[3].iov_len = pad_pktlen - pktlen; + + error = hv_ring_buffer_write(&chan->outbound, iov, 4, &send_evt); + if (!error && send_evt) + vmbus_chan_send_event(chan); + return error; } /** diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 1a9290e..a1bff12 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -42,34 +42,6 @@ struct vmbus_softc; /* - * The format must be the same as hv_vm_data_gpa_direct - */ -typedef struct hv_vmbus_channel_packet_page_buffer { - uint16_t type; - uint16_t data_offset8; - uint16_t length8; - uint16_t flags; - uint64_t transaction_id; - uint32_t reserved; - uint32_t range_count; - hv_vmbus_page_buffer range[HV_MAX_PAGE_BUFFER_COUNT]; -} __packed hv_vmbus_channel_packet_page_buffer; - -/* - * The format must be the same as hv_vm_data_gpa_direct - */ -typedef struct hv_vmbus_channel_packet_multipage_buffer { - uint16_t type; - uint16_t data_offset8; - uint16_t length8; - uint16_t flags; - uint64_t transaction_id; - uint32_t reserved; - uint32_t range_count; /* Always 1 in this case */ - hv_vmbus_multipage_buffer range; -} __packed hv_vmbus_channel_packet_multipage_buffer; - -/* * Private, VM Bus functions */ struct sysctl_ctx_list; diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h index 164c3a7..2a94f15 100644 --- a/sys/dev/hyperv/vmbus/vmbus_reg.h +++ b/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -30,8 +30,9 @@ #define _VMBUS_REG_H_ #include <sys/param.h> -#include <dev/hyperv/vmbus/hyperv_reg.h> #include <dev/hyperv/include/hyperv.h> /* XXX for hyperv_guid */ +#include <dev/hyperv/include/vmbus.h> +#include <dev/hyperv/vmbus/hyperv_reg.h> /* * Hyper-V SynIC message format. @@ -108,12 +109,36 @@ CTASSERT(sizeof(struct vmbus_mnf) == PAGE_SIZE); #define VMBUS_CHAN_MAX (VMBUS_EVTFLAG_LEN * VMBUS_EVTFLAGS_MAX) /* - * GPA range. + * Channel packets */ -struct vmbus_gpa_range { - uint32_t gpa_len; - uint32_t gpa_ofs; - uint64_t gpa_page[]; + +#define VMBUS_CHANPKT_SIZE_SHIFT 3 +#define VMBUS_CHANPKT_SIZE_ALIGN (1 << VMBUS_CHANPKT_SIZE_SHIFT) + +struct vmbus_chanpkt_hdr { + uint16_t cph_type; + uint16_t cph_data_ofs; /* in 8 bytes */ + uint16_t cph_len; /* in 8 bytes */ + uint16_t cph_flags; + uint64_t cph_xactid; +} __packed; + +struct vmbus_chanpkt { + struct vmbus_chanpkt_hdr cp_hdr; +} __packed; + +struct vmbus_chanpkt_sglist { + struct vmbus_chanpkt_hdr cp_hdr; + uint32_t cp_rsvd; + uint32_t cp_gpa_cnt; + struct vmbus_gpa cp_gpa[]; +} __packed; + +struct vmbus_chanpkt_prplist { + struct vmbus_chanpkt_hdr cp_hdr; + uint32_t cp_rsvd; + uint32_t cp_range_cnt; + struct vmbus_gpa_range cp_range[]; } __packed; /* |