diff options
author | sephe <sephe@FreeBSD.org> | 2016-10-14 08:02:37 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-10-14 08:02:37 +0000 |
commit | 5691021e808c20e7a770942b04bdb9e039d2f624 (patch) | |
tree | 8de1d9c8074cfd3e4e05d8575346267569092ac1 /sys/dev/hyperv | |
parent | 56da3ec17e37a6540c26f6be524c4c541e122690 (diff) | |
download | FreeBSD-src-5691021e808c20e7a770942b04bdb9e039d2f624.zip FreeBSD-src-5691021e808c20e7a770942b04bdb9e039d2f624.tar.gz |
MFC 302617-302621,302623,302629-302631
302617
hyperv/vmbus: Flatten channel message response processing.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6914
302618
hyperv/vmbus: Avoid tx_evtflags setting code duplication.
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6915
302619
hyperv/vmbus: Busdma-fy Hypercall signal event input parameter.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6916
302620
hyperv: Nuke unused stuffs
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6917
302621
hyperv/vmbus: Don't be oversmart in default cpu selection.
Pin the channel to cpu0 by default. Drivers having special channel-cpu
mapping requirement should call vmbus_channel_cpu_{set,rr}() themselves.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6918
302623
hyperv/vmbus: Minor renaming
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6919
302629
hyperv/vmbus: Rework vmbus version accessing.
Instead of global variable, vmbus version is accessed through
a vmbus DEVMETHOD now.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6953
302630
hyperv/vmbus: Move GPADL index into vmbus_softc
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6954
302631
hyperv/vmbus: Move channel list to vmbus_softc
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6956
Diffstat (limited to 'sys/dev/hyperv')
-rw-r--r-- | sys/dev/hyperv/include/hyperv.h | 40 | ||||
-rw-r--r-- | sys/dev/hyperv/include/hyperv_busdma.h | 4 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 30 | ||||
-rw-r--r-- | sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c | 11 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel.c | 18 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel_mgmt.c | 206 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_connection.c | 26 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 118 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hyperv.c | 35 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hyperv_reg.h | 12 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hyperv_var.h | 1 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus.c | 92 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_if.m | 37 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_reg.h | 26 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_var.h | 18 |
15 files changed, 257 insertions, 417 deletions
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 5c09231..b661b35 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -55,6 +55,7 @@ #include <amd64/include/xen/synch_bitops.h> #include <amd64/include/atomic.h> +#include <dev/hyperv/include/hyperv_busdma.h> typedef uint8_t hv_bool_uint8_t; @@ -72,10 +73,13 @@ typedef uint8_t hv_bool_uint8_t; * 2.4 -- Windows 8 * 3.0 -- Windows 8.1 */ -#define HV_VMBUS_VERSION_WS2008 ((0 << 16) | (13)) -#define HV_VMBUS_VERSION_WIN7 ((1 << 16) | (1)) -#define HV_VMBUS_VERSION_WIN8 ((2 << 16) | (4)) -#define HV_VMBUS_VERSION_WIN8_1 ((3 << 16) | (0)) +#define VMBUS_VERSION_WS2008 ((0 << 16) | (13)) +#define VMBUS_VERSION_WIN7 ((1 << 16) | (1)) +#define VMBUS_VERSION_WIN8 ((2 << 16) | (4)) +#define VMBUS_VERSION_WIN8_1 ((3 << 16) | (0)) + +#define VMBUS_VERSION_MAJOR(ver) (((uint32_t)(ver)) >> 16) +#define VMBUS_VERSION_MINOR(ver) (((uint32_t)(ver)) & 0xffff) /* * Make maximum size of pipe payload of 16K @@ -528,22 +532,7 @@ typedef union { } __packed hv_vmbus_connection_id; -/* - * Definition of the hv_vmbus_signal_event hypercall input structure - */ -typedef struct { - hv_vmbus_connection_id connection_id; - uint16_t flag_number; - uint16_t rsvd_z; -} __packed hv_vmbus_input_signal_event; - -typedef struct { - uint64_t align8; - hv_vmbus_input_signal_event event; -} __packed hv_vmbus_input_signal_event_buffer; - typedef struct hv_vmbus_channel { - TAILQ_ENTRY(hv_vmbus_channel) list_entry; struct hv_device* device; struct vmbus_softc *vmbus_sc; hv_vmbus_channel_state state; @@ -589,14 +578,8 @@ typedef struct hv_vmbus_channel { boolean_t is_dedicated_interrupt; - /* - * Used as an input param for HV_CALL_SIGNAL_EVENT hypercall. - */ - hv_vmbus_input_signal_event_buffer signal_event_buffer; - /* - * 8-bytes aligned of the buffer above - */ - hv_vmbus_input_signal_event *signal_event_param; + struct hypercall_sigevt_in *ch_sigevt; + struct hyperv_dma ch_sigevt_dma; /* * From Win8, this field specifies the target virtual process @@ -643,6 +626,7 @@ typedef struct hv_vmbus_channel { void *hv_chan_priv3; struct task ch_detach_task; + TAILQ_ENTRY(hv_vmbus_channel) ch_link; } hv_vmbus_channel; #define HV_VMBUS_CHAN_ISPRIMARY(chan) ((chan)->primary_channel == NULL) @@ -726,6 +710,7 @@ int hv_vmbus_channel_teardown_gpdal( struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary); void vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu); +void vmbus_channel_cpu_rr(struct hv_vmbus_channel *chan); struct hv_vmbus_channel ** vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt); void vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt); @@ -741,5 +726,4 @@ hv_get_phys_addr(void *virt) return (ret); } -extern uint32_t hv_vmbus_protocal_version; #endif /* __HYPERV_H__ */ diff --git a/sys/dev/hyperv/include/hyperv_busdma.h b/sys/dev/hyperv/include/hyperv_busdma.h index f4ea8cf..a27d2db 100644 --- a/sys/dev/hyperv/include/hyperv_busdma.h +++ b/sys/dev/hyperv/include/hyperv_busdma.h @@ -29,6 +29,10 @@ #ifndef _HYPERV_BUSDMA_H_ #define _HYPERV_BUSDMA_H_ +#include <sys/param.h> +#include <sys/bus.h> +#include <machine/bus.h> + struct hyperv_dma { bus_addr_t hv_paddr; bus_dma_tag_t hv_dtag; diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 5afb751..7bec32e 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -114,9 +114,11 @@ __FBSDID("$FreeBSD$"); #include <dev/hyperv/include/hyperv.h> #include <dev/hyperv/include/hyperv_busdma.h> + #include "hv_net_vsc.h" #include "hv_rndis.h" #include "hv_rndis_filter.h" +#include "vmbus_if.h" #define hv_chan_rxr hv_chan_priv1 #define hv_chan_txr hv_chan_priv2 @@ -2369,8 +2371,10 @@ static int hn_create_tx_ring(struct hn_softc *sc, int id) { struct hn_tx_ring *txr = &sc->hn_tx_ring[id]; + device_t dev = sc->hn_dev; bus_dma_tag_t parent_dtag; int error, i; + uint32_t version; txr->hn_sc = sc; txr->hn_tx_idx = id; @@ -2409,10 +2413,18 @@ hn_create_tx_ring(struct hn_softc *sc, int id) } txr->hn_direct_tx_size = hn_direct_tx_size; - if (hv_vmbus_protocal_version >= HV_VMBUS_VERSION_WIN8_1) + version = VMBUS_GET_VERSION(device_get_parent(dev), dev); + if (version >= VMBUS_VERSION_WIN8_1) { txr->hn_csum_assist = HN_CSUM_ASSIST; - else + } else { txr->hn_csum_assist = HN_CSUM_ASSIST_WIN8; + if (id == 0) { + device_printf(dev, "bus version %u.%u, " + "no UDP checksum offloading\n", + VMBUS_VERSION_MAJOR(version), + VMBUS_VERSION_MINOR(version)); + } + } /* * Always schedule transmission instead of trying to do direct @@ -2420,7 +2432,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) */ txr->hn_sched_tx = 1; - parent_dtag = bus_get_dma_tag(sc->hn_dev); + parent_dtag = bus_get_dma_tag(dev); /* DMA tag for RNDIS messages. */ error = bus_dma_tag_create(parent_dtag, /* parent */ @@ -2437,7 +2449,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) NULL, /* lockfuncarg */ &txr->hn_tx_rndis_dtag); if (error) { - device_printf(sc->hn_dev, "failed to create rndis dmatag\n"); + device_printf(dev, "failed to create rndis dmatag\n"); return error; } @@ -2456,7 +2468,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) NULL, /* lockfuncarg */ &txr->hn_tx_data_dtag); if (error) { - device_printf(sc->hn_dev, "failed to create data dmatag\n"); + device_printf(dev, "failed to create data dmatag\n"); return error; } @@ -2473,7 +2485,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) BUS_DMA_WAITOK | BUS_DMA_COHERENT, &txd->rndis_msg_dmap); if (error) { - device_printf(sc->hn_dev, + device_printf(dev, "failed to allocate rndis_msg, %d\n", i); return error; } @@ -2484,7 +2496,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) hyperv_dma_map_paddr, &txd->rndis_msg_paddr, BUS_DMA_NOWAIT); if (error) { - device_printf(sc->hn_dev, + device_printf(dev, "failed to load rndis_msg, %d\n", i); bus_dmamem_free(txr->hn_tx_rndis_dtag, txd->rndis_msg, txd->rndis_msg_dmap); @@ -2495,7 +2507,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) error = bus_dmamap_create(txr->hn_tx_data_dtag, 0, &txd->data_dmap); if (error) { - device_printf(sc->hn_dev, + device_printf(dev, "failed to allocate tx data dmamap\n"); bus_dmamap_unload(txr->hn_tx_rndis_dtag, txd->rndis_msg_dmap); @@ -2523,7 +2535,7 @@ hn_create_tx_ring(struct hn_softc *sc, int id) * Create per TX ring sysctl tree: * dev.hn.UNIT.tx.RINGID */ - ctx = device_get_sysctl_ctx(sc->hn_dev); + ctx = device_get_sysctl_ctx(dev); child = SYSCTL_CHILDREN(sc->hn_tx_sysctl_tree); snprintf(name, sizeof(name), "%d", id); diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index 7ec96ad..bb2f3bb 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -72,7 +72,9 @@ __FBSDID("$FreeBSD$"); #include <cam/scsi/scsi_message.h> #include <dev/hyperv/include/hyperv.h> + #include "hv_vstorage.h" +#include "vmbus_if.h" #define STORVSC_RINGBUFFER_SIZE (20*PAGE_SIZE) #define STORVSC_MAX_LUNS_PER_TARGET (64) @@ -361,6 +363,7 @@ storvsc_subchan_attach(struct hv_vmbus_channel *new_channel) memset(&props, 0, sizeof(props)); + vmbus_channel_cpu_rr(new_channel); ret = hv_vmbus_channel_open(new_channel, sc->hs_drv_props->drv_ringbuffer_size, sc->hs_drv_props->drv_ringbuffer_size, @@ -464,6 +467,7 @@ hv_storvsc_channel_init(struct hv_device *dev) struct storvsc_softc *sc; uint16_t max_chans = 0; boolean_t support_multichannel = FALSE; + uint32_t version; max_chans = 0; support_multichannel = FALSE; @@ -588,8 +592,9 @@ hv_storvsc_channel_init(struct hv_device *dev) /* multi-channels feature is supported by WIN8 and above version */ max_chans = vstor_packet->u.chan_props.max_channel_cnt; - if ((hv_vmbus_protocal_version != HV_VMBUS_VERSION_WIN7) && - (hv_vmbus_protocal_version != HV_VMBUS_VERSION_WS2008) && + version = VMBUS_GET_VERSION(device_get_parent(dev->device), + dev->device); + if (version != VMBUS_VERSION_WIN7 && version != VMBUS_VERSION_WS2008 && (vstor_packet->u.chan_props.flags & HV_STORAGE_SUPPORTS_MULTI_CHANNEL)) { support_multichannel = TRUE; @@ -655,7 +660,7 @@ hv_storvsc_connect_vsp(struct hv_device *dev) /* * Open the channel */ - + vmbus_channel_cpu_rr(dev->channel); ret = hv_vmbus_channel_open( dev->channel, sc->hs_drv_props->drv_ringbuffer_size, diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index 14290fd..14bc16f 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <vm/pmap.h> #include <dev/hyperv/vmbus/hv_vmbus_priv.h> +#include <dev/hyperv/vmbus/hyperv_var.h> #include <dev/hyperv/vmbus/vmbus_reg.h> #include <dev/hyperv/vmbus/vmbus_var.h> @@ -58,21 +59,21 @@ static void VmbusProcessChannelEvent(void* channel, int pending); static void vmbus_channel_set_event(hv_vmbus_channel *channel) { + struct vmbus_softc *sc = channel->vmbus_sc; + uint32_t chanid = channel->offer_msg.child_rel_id; + + atomic_set_long(&sc->vmbus_tx_evtflags[chanid >> VMBUS_EVTFLAG_SHIFT], + 1UL << (chanid & VMBUS_EVTFLAG_MASK)); + if (channel->offer_msg.monitor_allocated) { - struct vmbus_softc *sc = channel->vmbus_sc; hv_vmbus_monitor_page *monitor_page; - uint32_t chanid = channel->offer_msg.child_rel_id; - - atomic_set_long( - &sc->vmbus_tx_evtflags[chanid >> VMBUS_EVTFLAG_SHIFT], - 1UL << (chanid & VMBUS_EVTFLAG_MASK)); monitor_page = sc->vmbus_mnf2; synch_set_bit(channel->monitor_bit, (uint32_t *)&monitor_page-> trigger_group[channel->monitor_group].u.pending); } else { - hv_vmbus_set_event(channel); + hypercall_signal_event(channel->ch_sigevt_dma.hv_paddr); } } @@ -342,8 +343,7 @@ hv_vmbus_channel_establish_gpadl(struct hv_vmbus_channel *channel, /* * Allocate GPADL id. */ - gpadl = atomic_fetchadd_int( - &hv_vmbus_g_connection.next_gpadl_handle, 1); + gpadl = vmbus_gpadl_alloc(sc); *gpadl0 = gpadl; /* diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c index ae708cc..ce1b003b 100644 --- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -32,6 +32,7 @@ #include <sys/mbuf.h> #include <sys/mutex.h> +#include <dev/hyperv/include/hyperv_busdma.h> #include <dev/hyperv/vmbus/hv_vmbus_priv.h> #include <dev/hyperv/vmbus/vmbus_reg.h> #include <dev/hyperv/vmbus/vmbus_var.h> @@ -46,18 +47,10 @@ static void vmbus_chan_detach_task(void *, int); static void vmbus_channel_on_offer(struct vmbus_softc *, const struct vmbus_message *); -static void vmbus_channel_on_open_result(struct vmbus_softc *, - const struct vmbus_message *); static void vmbus_channel_on_offer_rescind(struct vmbus_softc *, const struct vmbus_message *); -static void vmbus_channel_on_gpadl_created(struct vmbus_softc *, - const struct vmbus_message *); -static void vmbus_channel_on_gpadl_torndown(struct vmbus_softc *, - const struct vmbus_message *); static void vmbus_channel_on_offers_delivered(struct vmbus_softc *, const struct vmbus_message *); -static void vmbus_channel_on_version_response(struct vmbus_softc *, - const struct vmbus_message *); /** * Channel message dispatch table @@ -71,13 +64,13 @@ vmbus_chanmsg_process[HV_CHANNEL_MESSAGE_COUNT] = { [HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED] = vmbus_channel_on_offers_delivered, [HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT] = - vmbus_channel_on_open_result, + vmbus_msghc_wakeup, [HV_CHANNEL_MESSAGE_GPADL_CREATED] = - vmbus_channel_on_gpadl_created, + vmbus_msghc_wakeup, [HV_CHANNEL_MESSAGE_GPADL_TORNDOWN] = - vmbus_channel_on_gpadl_torndown, + vmbus_msghc_wakeup, [HV_CHANNEL_MESSAGE_VERSION_RESPONSE] = - vmbus_channel_on_version_response + vmbus_msghc_wakeup }; /** @@ -115,6 +108,7 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel) static void vmbus_channel_process_offer(hv_vmbus_channel *new_channel) { + struct vmbus_softc *sc = new_channel->vmbus_sc; hv_vmbus_channel* channel; uint32_t relid; @@ -122,7 +116,7 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) /* * Make sure this is a new offer */ - mtx_lock(&hv_vmbus_g_connection.channel_lock); + mtx_lock(&sc->vmbus_chlist_lock); if (relid == 0) { /* * XXX channel0 will not be processed; skip it. @@ -132,8 +126,7 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) hv_vmbus_g_connection.channels[relid] = new_channel; } - TAILQ_FOREACH(channel, &hv_vmbus_g_connection.channel_anchor, - list_entry) { + TAILQ_FOREACH(channel, &sc->vmbus_chlist, ch_link) { if (memcmp(&channel->offer_msg.offer.interface_type, &new_channel->offer_msg.offer.interface_type, sizeof(hv_guid)) == 0 && @@ -145,10 +138,9 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) if (channel == NULL) { /* Install the new primary channel */ - TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor, - new_channel, list_entry); + TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, ch_link); } - mtx_unlock(&hv_vmbus_g_connection.channel_lock); + mtx_unlock(&sc->vmbus_chlist_lock); if (channel != NULL) { /* @@ -172,11 +164,19 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) new_channel->offer_msg.offer.sub_channel_index); } - /* Insert new channel into channel_anchor. */ - mtx_lock(&hv_vmbus_g_connection.channel_lock); - TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor, - new_channel, list_entry); - mtx_unlock(&hv_vmbus_g_connection.channel_lock); + /* + * Insert the new channel to the end of the global + * channel list. + * + * NOTE: + * The new sub-channel MUST be inserted AFTER it's + * primary channel, so that the primary channel will + * be found in the above loop for its baby siblings. + */ + mtx_lock(&sc->vmbus_chlist_lock); + TAILQ_INSERT_TAIL(&sc->vmbus_chlist, new_channel, + ch_link); + mtx_unlock(&sc->vmbus_chlist_lock); if(bootverbose) printf("VMBUS: new multi-channel offer <%p>, " @@ -229,8 +229,8 @@ vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu) { KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpu %d", cpu)); - if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 || - hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) { + if (chan->vmbus_sc->vmbus_version == VMBUS_VERSION_WS2008 || + chan->vmbus_sc->vmbus_version == VMBUS_VERSION_WIN7) { /* Only cpu0 is supported */ cpu = 0; } @@ -245,61 +245,25 @@ vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu) } } -/** - * Array of device guids that are performance critical. We try to distribute - * the interrupt load for these devices across all online cpus. - */ -static const hv_guid high_perf_devices[] = { - {HV_NIC_GUID, }, - {HV_IDE_GUID, }, - {HV_SCSI_GUID, }, -}; - -enum { - PERF_CHN_NIC = 0, - PERF_CHN_IDE, - PERF_CHN_SCSI, - MAX_PERF_CHN, -}; +void +vmbus_channel_cpu_rr(struct hv_vmbus_channel *chan) +{ + static uint32_t vmbus_chan_nextcpu; + int cpu; -/* - * We use this static number to distribute the channel interrupt load. - */ -static uint32_t next_vcpu; + cpu = atomic_fetchadd_int(&vmbus_chan_nextcpu, 1) % mp_ncpus; + vmbus_channel_cpu_set(chan, cpu); +} -/** - * Starting with Win8, we can statically distribute the incoming - * channel interrupt load by binding a channel to VCPU. We - * implement here a simple round robin scheme for distributing - * the interrupt load. - * We will bind channels that are not performance critical to cpu 0 and - * performance critical channels (IDE, SCSI and Network) will be uniformly - * distributed across all available CPUs. - */ static void -vmbus_channel_select_defcpu(struct hv_vmbus_channel *channel) +vmbus_channel_select_defcpu(struct hv_vmbus_channel *chan) { - uint32_t current_cpu; - int i; - boolean_t is_perf_channel = FALSE; - const hv_guid *guid = &channel->offer_msg.offer.interface_type; - - for (i = PERF_CHN_NIC; i < MAX_PERF_CHN; i++) { - if (memcmp(guid->data, high_perf_devices[i].data, - sizeof(hv_guid)) == 0) { - is_perf_channel = TRUE; - break; - } - } - - if (!is_perf_channel) { - /* Stick to cpu0 */ - vmbus_channel_cpu_set(channel, 0); - return; - } - /* mp_ncpus should have the number cpus currently online */ - current_cpu = (++next_vcpu % mp_ncpus); - vmbus_channel_cpu_set(channel, current_cpu); + /* + * By default, pin the channel to cpu0. Devices having + * special channel-cpu mapping requirement should call + * vmbus_channel_cpu_{set,rr}(). + */ + vmbus_channel_cpu_set(chan, 0); } /** @@ -335,23 +299,23 @@ vmbus_channel_on_offer_internal(struct vmbus_softc *sc, */ new_channel->batched_reading = TRUE; - new_channel->signal_event_param = - (hv_vmbus_input_signal_event *) - (HV_ALIGN_UP((unsigned long) - &new_channel->signal_event_buffer, - HV_HYPERCALL_PARAM_ALIGN)); - - new_channel->signal_event_param->connection_id.as_uint32_t = 0; - new_channel->signal_event_param->connection_id.u.id = - HV_VMBUS_EVENT_CONNECTION_ID; - new_channel->signal_event_param->flag_number = 0; - new_channel->signal_event_param->rsvd_z = 0; + new_channel->ch_sigevt = hyperv_dmamem_alloc( + bus_get_dma_tag(sc->vmbus_dev), + HYPERCALL_SIGEVTIN_ALIGN, 0, sizeof(struct hypercall_sigevt_in), + &new_channel->ch_sigevt_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); + if (new_channel->ch_sigevt == NULL) { + device_printf(sc->vmbus_dev, "sigevt alloc failed\n"); + /* XXX */ + mtx_destroy(&new_channel->sc_lock); + free(new_channel, M_DEVBUF); + return; + } + new_channel->ch_sigevt->hc_connid = VMBUS_CONNID_EVENT; - if (hv_vmbus_protocal_version != HV_VMBUS_VERSION_WS2008) { + if (sc->vmbus_version != VMBUS_VERSION_WS2008) { new_channel->is_dedicated_interrupt = (offer->is_dedicated_interrupt != 0); - new_channel->signal_event_param->connection_id.u.id = - offer->connection_id; + new_channel->ch_sigevt->hc_connid = offer->connection_id; } memcpy(&new_channel->offer_msg, offer, @@ -415,67 +379,18 @@ 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. - */ -static void -vmbus_channel_on_open_result(struct vmbus_softc *sc, - const struct vmbus_message *msg) -{ - vmbus_msghc_wakeup(sc, msg); -} - -/** - * @brief GPADL created handler. - * - * This is invoked when we received a response - * to our gpadl create request. Find the matching request, copy the - * response and signal the requesting thread. - */ -static void -vmbus_channel_on_gpadl_created(struct vmbus_softc *sc, - const struct vmbus_message *msg) -{ - vmbus_msghc_wakeup(sc, msg); -} - -/** - * @brief GPADL torndown handler. - * - * This is invoked when we received a respons - * to our gpadl teardown request. Find the matching request, copy the - * response and signal the requesting thread - */ -static void -vmbus_channel_on_gpadl_torndown(struct vmbus_softc *sc, - const struct vmbus_message *msg) -{ - vmbus_msghc_wakeup(sc, msg); -} - -static void -vmbus_channel_on_version_response(struct vmbus_softc *sc, - const struct vmbus_message *msg) -{ - vmbus_msghc_wakeup(sc, msg); -} - -/** * @brief Release channels that are unattached/unconnected (i.e., no drivers associated) */ void -hv_vmbus_release_unattached_channels(void) +hv_vmbus_release_unattached_channels(struct vmbus_softc *sc) { hv_vmbus_channel *channel; - mtx_lock(&hv_vmbus_g_connection.channel_lock); + mtx_lock(&sc->vmbus_chlist_lock); - while (!TAILQ_EMPTY(&hv_vmbus_g_connection.channel_anchor)) { - channel = TAILQ_FIRST(&hv_vmbus_g_connection.channel_anchor); - TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor, - channel, list_entry); + while (!TAILQ_EMPTY(&sc->vmbus_chlist)) { + channel = TAILQ_FIRST(&sc->vmbus_chlist); + TAILQ_REMOVE(&sc->vmbus_chlist, channel, ch_link); if (HV_VMBUS_CHAN_ISPRIMARY(channel)) { /* Only primary channel owns the hv_device */ @@ -485,7 +400,8 @@ hv_vmbus_release_unattached_channels(void) } bzero(hv_vmbus_g_connection.channels, sizeof(hv_vmbus_channel*) * VMBUS_CHAN_MAX); - mtx_unlock(&hv_vmbus_g_connection.channel_lock); + + mtx_unlock(&sc->vmbus_chlist_lock); } /** diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c index b68ed59..8a2b4e7 100644 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ b/sys/dev/hyperv/vmbus/hv_connection.c @@ -47,10 +47,7 @@ * Globals */ hv_vmbus_connection hv_vmbus_g_connection = - { .connect_state = HV_DISCONNECTED, - .next_gpadl_handle = 0xE1E10, }; - -uint32_t hv_vmbus_protocal_version; + { .connect_state = HV_DISCONNECTED }; /** * Send a connect request on the partition service connection @@ -70,10 +67,6 @@ hv_vmbus_connect(struct vmbus_softc *sc) */ hv_vmbus_g_connection.connect_state = HV_CONNECTING; - TAILQ_INIT(&hv_vmbus_g_connection.channel_anchor); - mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel", - NULL, MTX_DEF); - hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) * VMBUS_CHAN_MAX, M_DEVBUF, M_WAITOK | M_ZERO); @@ -158,23 +151,6 @@ vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu) } } -/** - * Send an event notification to the parent - */ -int -hv_vmbus_set_event(hv_vmbus_channel *channel) -{ - struct vmbus_softc *sc = channel->vmbus_sc; - int ret = 0; - uint32_t chanid = channel->offer_msg.child_rel_id; - - atomic_set_long(&sc->vmbus_tx_evtflags[chanid >> VMBUS_EVTFLAG_SHIFT], - 1UL << (chanid & VMBUS_EVTFLAG_MASK)); - ret = hv_vmbus_signal_event(channel->signal_event_param); - - return (ret); -} - void vmbus_on_channel_open(const struct hv_vmbus_channel *chan) { diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 5e5a15c..1dd5251 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -38,28 +38,7 @@ #include <dev/hyperv/include/hyperv.h> - -/* - * Status codes for hypervisor operations. - */ - -typedef uint16_t hv_vmbus_status; - -#define HV_MESSAGE_SIZE (256) -#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240) -#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30) -#define HV_ANY_VP (0xFFFFFFFF) - -/* - * MessageId: HV_STATUS_INSUFFICIENT_BUFFERS - * MessageText: - * You did not supply enough message buffers to send a message. - */ - -#define HV_STATUS_SUCCESS ((uint16_t)0) -#define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013) - -typedef void (*hv_vmbus_channel_callback)(void *context); +struct vmbus_softc; typedef struct { void* data; @@ -118,74 +97,6 @@ typedef struct hv_vmbus_channel_packet_multipage_buffer { hv_vmbus_multipage_buffer range; } __packed hv_vmbus_channel_packet_multipage_buffer; -enum { - HV_VMBUS_MESSAGE_CONNECTION_ID = 1, - HV_VMBUS_MESSAGE_PORT_ID = 1, - HV_VMBUS_EVENT_CONNECTION_ID = 2, - HV_VMBUS_EVENT_PORT_ID = 2, - HV_VMBUS_MONITOR_CONNECTION_ID = 3, - HV_VMBUS_MONITOR_PORT_ID = 3, -}; - -#define HV_PRESENT_BIT 0x80000000 - -#define HV_HYPERCALL_PARAM_ALIGN sizeof(uint64_t) - -/* - * Define hypervisor message types - */ -typedef enum { - - HV_MESSAGE_TYPE_NONE = 0x00000000, - - /* - * Memory access messages - */ - HV_MESSAGE_TYPE_UNMAPPED_GPA = 0x80000000, - HV_MESSAGE_TYPE_GPA_INTERCEPT = 0x80000001, - - /* - * Timer notification messages - */ - HV_MESSAGE_TIMER_EXPIRED = 0x80000010, - - /* - * Error messages - */ - HV_MESSAGE_TYPE_INVALID_VP_REGISTER_VALUE = 0x80000020, - HV_MESSAGE_TYPE_UNRECOVERABLE_EXCEPTION = 0x80000021, - HV_MESSAGE_TYPE_UNSUPPORTED_FEATURE = 0x80000022, - - /* - * Trace buffer complete messages - */ - HV_MESSAGE_TYPE_EVENT_LOG_BUFFER_COMPLETE = 0x80000040, - - /* - * Platform-specific processor intercept messages - */ - HV_MESSAGE_TYPE_X64_IO_PORT_INTERCEPT = 0x80010000, - HV_MESSAGE_TYPE_X64_MSR_INTERCEPT = 0x80010001, - HV_MESSAGE_TYPE_X64_CPU_INTERCEPT = 0x80010002, - HV_MESSAGE_TYPE_X64_EXCEPTION_INTERCEPT = 0x80010003, - HV_MESSAGE_TYPE_X64_APIC_EOI = 0x80010004, - HV_MESSAGE_TYPE_X64_LEGACY_FP_ERROR = 0x80010005 - -} hv_vmbus_msg_type; - -/* - * Define port identifier type - */ -typedef union _hv_vmbus_port_id { - uint32_t as_uint32_t; - struct { - uint32_t id:24; - uint32_t reserved:8; - } u ; -} hv_vmbus_port_id; - -typedef uint64_t hv_vmbus_partition_id; - /* * VM Bus connection states */ @@ -196,19 +107,8 @@ typedef enum { HV_DISCONNECTING } hv_vmbus_connect_state; -#define HV_MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT - - typedef struct { hv_vmbus_connect_state connect_state; - uint32_t next_gpadl_handle; - - /** - * List of primary channels. Sub channels will be linked - * under their primary channel. - */ - TAILQ_HEAD(, hv_vmbus_channel) channel_anchor; - struct mtx channel_lock; /** * channel table for fast lookup through id. @@ -277,14 +177,6 @@ typedef struct { uint8_t rsvd_z4[1984]; } hv_vmbus_monitor_page; -/* - * Declare the various hypercall operations - */ -typedef enum { - HV_CALL_POST_MESSAGE = 0x005c, - HV_CALL_SIGNAL_EVENT = 0x005d, -} hv_vmbus_call_code; - /** * Global variables */ @@ -342,17 +234,14 @@ uint32_t hv_ring_buffer_read_end( hv_vmbus_ring_buffer_info *ring_info); void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel); -void hv_vmbus_release_unattached_channels(void); - -uint16_t hv_vmbus_signal_event(void *con_id); +void hv_vmbus_release_unattached_channels( + struct vmbus_softc *); struct hv_device* hv_vmbus_child_device_create( hv_guid device_type, hv_guid device_instance, hv_vmbus_channel *channel); -struct vmbus_softc; - void hv_vmbus_child_device_register(struct vmbus_softc *, struct hv_device *child_dev); int hv_vmbus_child_device_unregister( @@ -363,6 +252,5 @@ int hv_vmbus_child_device_unregister( */ int hv_vmbus_connect(struct vmbus_softc *); int hv_vmbus_disconnect(void); -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 94ef5fa..c2ad3519 100644 --- a/sys/dev/hyperv/vmbus/hyperv.c +++ b/sys/dev/hyperv/vmbus/hyperv.c @@ -101,23 +101,6 @@ hyperv_get_timecount(struct timecounter *tc __unused) return rdmsr(MSR_HV_TIME_REF_COUNT); } -/** - * @brief Invoke the specified hypercall - */ -static uint64_t -hv_vmbus_do_hypercall(uint64_t value, void *input, void *output) -{ - uint64_t in_paddr = 0, out_paddr = 0; - - if (input != NULL) - in_paddr = hv_get_phys_addr(input); - if (output != NULL) - out_paddr = hv_get_phys_addr(output); - - return hypercall_md(hypercall_context.hc_addr, value, - in_paddr, out_paddr); -} - uint64_t hypercall_post_message(bus_addr_t msg_paddr) { @@ -125,21 +108,11 @@ hypercall_post_message(bus_addr_t msg_paddr) HYPERCALL_POST_MESSAGE, msg_paddr, 0); } -/** - * @brief Signal an event on the specified connection using the hypervisor - * event IPC. (This involves a hypercall.) - */ -hv_vmbus_status -hv_vmbus_signal_event(void *con_id) +uint64_t +hypercall_signal_event(bus_addr_t sigevt_paddr) { - hv_vmbus_status status; - - status = hv_vmbus_do_hypercall( - HV_CALL_SIGNAL_EVENT, - con_id, - 0) & 0xFFFF; - - return (status); + return hypercall_md(hypercall_context.hc_addr, + HYPERCALL_SIGNAL_EVENT, sigevt_paddr, 0); } int diff --git a/sys/dev/hyperv/vmbus/hyperv_reg.h b/sys/dev/hyperv/vmbus/hyperv_reg.h index f1a9e99..20f4810 100644 --- a/sys/dev/hyperv/vmbus/hyperv_reg.h +++ b/sys/dev/hyperv/vmbus/hyperv_reg.h @@ -148,6 +148,7 @@ * Hypercall input values */ #define HYPERCALL_POST_MESSAGE 0x005c +#define HYPERCALL_SIGNAL_EVENT 0x005d /* * Hypercall input parameters @@ -169,4 +170,15 @@ struct hypercall_postmsg_in { } __packed; CTASSERT(sizeof(struct hypercall_postmsg_in) == HYPERCALL_POSTMSGIN_SIZE); +/* + * HYPERCALL_SIGNAL_EVENT + */ +#define HYPERCALL_SIGEVTIN_ALIGN 8 + +struct hypercall_sigevt_in { + uint32_t hc_connid; + uint16_t hc_evtflag_ofs; + uint16_t hc_rsvd; +} __packed; + #endif /* !_HYPERV_REG_H_ */ diff --git a/sys/dev/hyperv/vmbus/hyperv_var.h b/sys/dev/hyperv/vmbus/hyperv_var.h index f16a017..3ea0c18 100644 --- a/sys/dev/hyperv/vmbus/hyperv_var.h +++ b/sys/dev/hyperv/vmbus/hyperv_var.h @@ -39,5 +39,6 @@ extern u_int hyperv_features; extern u_int hyperv_recommends; uint64_t hypercall_post_message(bus_addr_t msg_paddr); +uint64_t hypercall_signal_event(bus_addr_t sigevt_paddr); #endif /* !_HYPERV_VAR_H_ */ diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c index f7e1e53..80c082d 100644 --- a/sys/dev/hyperv/vmbus/vmbus.c +++ b/sys/dev/hyperv/vmbus/vmbus.c @@ -68,12 +68,9 @@ __FBSDID("$FreeBSD$"); #include <contrib/dev/acpica/include/acpi.h> #include "acpi_if.h" +#include "vmbus_if.h" -/* - * NOTE: DO NOT CHANGE THESE - */ -#define VMBUS_CONNID_MESSAGE 1 -#define VMBUS_CONNID_EVENT 2 +#define VMBUS_GPADL_START 0xe1e10 struct vmbus_msghc { struct hypercall_postmsg_in *mh_inprm; @@ -96,10 +93,9 @@ struct vmbus_msghc_ctx { #define VMBUS_MSGHC_CTXF_DESTROY 0x0001 static int vmbus_init(struct vmbus_softc *); -static int vmbus_init_contact(struct vmbus_softc *, - uint32_t); +static int vmbus_connect(struct vmbus_softc *, uint32_t); static int vmbus_req_channels(struct vmbus_softc *sc); -static void vmbus_uninit(struct vmbus_softc *); +static void vmbus_disconnect(struct vmbus_softc *); static int vmbus_scan(struct vmbus_softc *); static void vmbus_scan_wait(struct vmbus_softc *); static void vmbus_scan_newdev(struct vmbus_softc *); @@ -120,10 +116,10 @@ struct vmbus_softc *vmbus_sc; extern inthand_t IDTVEC(vmbus_isr); static const uint32_t vmbus_version[] = { - HV_VMBUS_VERSION_WIN8_1, - HV_VMBUS_VERSION_WIN8, - HV_VMBUS_VERSION_WIN7, - HV_VMBUS_VERSION_WS2008 + VMBUS_VERSION_WIN8_1, + VMBUS_VERSION_WIN8, + VMBUS_VERSION_WIN7, + VMBUS_VERSION_WS2008 }; static struct vmbus_msghc * @@ -378,21 +374,26 @@ vmbus_msghc_wakeup(struct vmbus_softc *sc, const struct vmbus_message *msg) wakeup(&mhc->mhc_active); } +uint32_t +vmbus_gpadl_alloc(struct vmbus_softc *sc) +{ + return atomic_fetchadd_int(&sc->vmbus_gpadl, 1); +} + static int -vmbus_init_contact(struct vmbus_softc *sc, uint32_t version) +vmbus_connect(struct vmbus_softc *sc, uint32_t version) { - struct vmbus_chanmsg_init_contact *req; - const struct vmbus_chanmsg_version_resp *resp; + struct vmbus_chanmsg_connect *req; const struct vmbus_message *msg; struct vmbus_msghc *mh; - int error, supp = 0; + int error, done = 0; mh = vmbus_msghc_get(sc, sizeof(*req)); if (mh == NULL) return ENXIO; req = vmbus_msghc_dataptr(mh); - req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_INIT_CONTACT; + req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CONNECT; req->chm_ver = version; req->chm_evtflags = sc->vmbus_evtflags_dma.hv_paddr; req->chm_mnf1 = sc->vmbus_mnf1_dma.hv_paddr; @@ -405,12 +406,12 @@ vmbus_init_contact(struct vmbus_softc *sc, uint32_t version) } msg = vmbus_msghc_wait_result(sc, mh); - resp = (const struct vmbus_chanmsg_version_resp *)msg->msg_data; - supp = resp->chm_supp; + done = ((const struct vmbus_chanmsg_connect_resp *) + msg->msg_data)->chm_done; vmbus_msghc_put(sc, mh); - return (supp ? 0 : EOPNOTSUPP); + return (done ? 0 : EOPNOTSUPP); } static int @@ -421,12 +422,12 @@ vmbus_init(struct vmbus_softc *sc) for (i = 0; i < nitems(vmbus_version); ++i) { int error; - error = vmbus_init_contact(sc, vmbus_version[i]); + error = vmbus_connect(sc, vmbus_version[i]); if (!error) { - hv_vmbus_protocal_version = vmbus_version[i]; + sc->vmbus_version = vmbus_version[i]; device_printf(sc->vmbus_dev, "version %u.%u\n", - (hv_vmbus_protocal_version >> 16), - (hv_vmbus_protocal_version & 0xffff)); + VMBUS_VERSION_MAJOR(sc->vmbus_version), + VMBUS_VERSION_MINOR(sc->vmbus_version)); return 0; } } @@ -434,35 +435,35 @@ vmbus_init(struct vmbus_softc *sc) } static void -vmbus_uninit(struct vmbus_softc *sc) +vmbus_disconnect(struct vmbus_softc *sc) { - struct vmbus_chanmsg_unload *req; + struct vmbus_chanmsg_disconnect *req; struct vmbus_msghc *mh; int error; mh = vmbus_msghc_get(sc, sizeof(*req)); if (mh == NULL) { device_printf(sc->vmbus_dev, - "can not get msg hypercall for unload\n"); + "can not get msg hypercall for disconnect\n"); return; } req = vmbus_msghc_dataptr(mh); - req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_UNLOAD; + req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_DISCONNECT; error = vmbus_msghc_exec_noresult(mh); vmbus_msghc_put(sc, mh); if (error) { device_printf(sc->vmbus_dev, - "unload msg hypercall failed\n"); + "disconnect msg hypercall failed\n"); } } static int vmbus_req_channels(struct vmbus_softc *sc) { - struct vmbus_chanmsg_channel_req *req; + struct vmbus_chanmsg_chrequest *req; struct vmbus_msghc *mh; int error; @@ -471,7 +472,7 @@ vmbus_req_channels(struct vmbus_softc *sc) return ENXIO; req = vmbus_msghc_dataptr(mh); - req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHANNEL_REQ; + req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHREQUEST; error = vmbus_msghc_exec_noresult(mh); vmbus_msghc_put(sc, mh); @@ -1072,14 +1073,23 @@ hv_vmbus_child_device_unregister(struct hv_device *child_dev) static int vmbus_sysctl_version(SYSCTL_HANDLER_ARGS) { + struct vmbus_softc *sc = arg1; char verstr[16]; snprintf(verstr, sizeof(verstr), "%u.%u", - hv_vmbus_protocal_version >> 16, - hv_vmbus_protocal_version & 0xffff); + VMBUS_VERSION_MAJOR(sc->vmbus_version), + VMBUS_VERSION_MINOR(sc->vmbus_version)); return sysctl_handle_string(oidp, verstr, sizeof(verstr), req); } +static uint32_t +vmbus_get_version_method(device_t bus, device_t dev) +{ + struct vmbus_softc *sc = device_get_softc(bus); + + return sc->vmbus_version; +} + static int vmbus_probe(device_t dev) { @@ -1119,6 +1129,9 @@ vmbus_doattach(struct vmbus_softc *sc) sc->vmbus_flags |= VMBUS_FLAG_ATTACHED; mtx_init(&sc->vmbus_scan_lock, "vmbus scan", NULL, MTX_DEF); + sc->vmbus_gpadl = VMBUS_GPADL_START; + mtx_init(&sc->vmbus_chlist_lock, "vmbus chlist", NULL, MTX_DEF); + TAILQ_INIT(&sc->vmbus_chlist); /* * Create context for "post message" Hypercalls @@ -1163,8 +1176,8 @@ vmbus_doattach(struct vmbus_softc *sc) if (ret != 0) goto cleanup; - if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 || - hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) + if (sc->vmbus_version == VMBUS_VERSION_WS2008 || + sc->vmbus_version == VMBUS_VERSION_WIN7) sc->vmbus_event_proc = vmbus_event_proc_compat; else sc->vmbus_event_proc = vmbus_event_proc; @@ -1176,7 +1189,7 @@ vmbus_doattach(struct vmbus_softc *sc) ctx = device_get_sysctl_ctx(sc->vmbus_dev); child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vmbus_dev)); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "version", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, vmbus_sysctl_version, "A", "vmbus version"); return (ret); @@ -1251,9 +1264,9 @@ vmbus_detach(device_t dev) { struct vmbus_softc *sc = device_get_softc(dev); - hv_vmbus_release_unattached_channels(); + hv_vmbus_release_unattached_channels(sc); - vmbus_uninit(sc); + vmbus_disconnect(sc); hv_vmbus_disconnect(); if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) { @@ -1289,6 +1302,9 @@ static device_method_t vmbus_methods[] = { DEVMETHOD(bus_write_ivar, vmbus_write_ivar), DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str), + /* Vmbus interface */ + DEVMETHOD(vmbus_get_version, vmbus_get_version_method), + DEVMETHOD_END }; diff --git a/sys/dev/hyperv/vmbus/vmbus_if.m b/sys/dev/hyperv/vmbus/vmbus_if.m new file mode 100644 index 0000000..0782d00 --- /dev/null +++ b/sys/dev/hyperv/vmbus/vmbus_if.m @@ -0,0 +1,37 @@ +#- +# 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$ +# + +#include <sys/param.h> +#include <sys/bus.h> + +INTERFACE vmbus; + +METHOD uint32_t get_version { + device_t bus; + device_t dev; +}; diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h index 767879e..df804d3 100644 --- a/sys/dev/hyperv/vmbus/vmbus_reg.h +++ b/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -93,7 +93,7 @@ struct vmbus_gpa_range { * - Embedded in hypercall_postmsg_in.hc_data, e.g. request. */ -#define VMBUS_CHANMSG_TYPE_CHANNEL_REQ 3 /* REQ */ +#define VMBUS_CHANMSG_TYPE_CHREQUEST 3 /* REQ */ #define VMBUS_CHANMSG_TYPE_CHOPEN 5 /* REQ */ #define VMBUS_CHANMSG_TYPE_CHOPEN_RESP 6 /* RESP */ #define VMBUS_CHANMSG_TYPE_CHCLOSE 7 /* REQ */ @@ -102,17 +102,17 @@ struct vmbus_gpa_range { #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 */ +#define VMBUS_CHANMSG_TYPE_CONNECT 14 /* REQ */ +#define VMBUS_CHANMSG_TYPE_CONNECT_RESP 15 /* RESP */ +#define VMBUS_CHANMSG_TYPE_DISCONNECT 16 /* REQ */ struct vmbus_chanmsg_hdr { uint32_t chm_type; /* VMBUS_CHANMSG_TYPE_ */ uint32_t chm_rsvd; } __packed; -/* VMBUS_CHANMSG_TYPE_INIT_CONTACT */ -struct vmbus_chanmsg_init_contact { +/* VMBUS_CHANMSG_TYPE_CONNECT */ +struct vmbus_chanmsg_connect { struct vmbus_chanmsg_hdr chm_hdr; uint32_t chm_ver; uint32_t chm_rsvd; @@ -121,19 +121,19 @@ struct vmbus_chanmsg_init_contact { uint64_t chm_mnf2; } __packed; -/* VMBUS_CHANMSG_TYPE_VERSION_RESP */ -struct vmbus_chanmsg_version_resp { +/* VMBUS_CHANMSG_TYPE_CONNECT_RESP */ +struct vmbus_chanmsg_connect_resp { struct vmbus_chanmsg_hdr chm_hdr; - uint8_t chm_supp; + uint8_t chm_done; } __packed; -/* VMBUS_CHANMSG_TYPE_CHANNEL_REQ */ -struct vmbus_chanmsg_channel_req { +/* VMBUS_CHANMSG_TYPE_CHREQUEST */ +struct vmbus_chanmsg_chrequest { struct vmbus_chanmsg_hdr chm_hdr; } __packed; -/* VMBUS_CHANMSG_TYPE_UNLOAD */ -struct vmbus_chanmsg_unload { +/* VMBUS_CHANMSG_TYPE_DISCONNECT */ +struct vmbus_chanmsg_disconnect { struct vmbus_chanmsg_hdr chm_hdr; } __packed; diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h index 2311fd5..2a60a48 100644 --- a/sys/dev/hyperv/vmbus/vmbus_var.h +++ b/sys/dev/hyperv/vmbus/vmbus_var.h @@ -46,6 +46,12 @@ */ #define VMBUS_SINT_TIMER 4 +/* + * NOTE: DO NOT CHANGE THESE + */ +#define VMBUS_CONNID_MESSAGE 1 +#define VMBUS_CONNID_EVENT 2 + struct vmbus_pcpu_data { u_long *intr_cnt; /* Hyper-V interrupt counter */ struct vmbus_message *message; /* shared messages */ @@ -72,10 +78,15 @@ struct vmbus_softc { struct vmbus_msghc_ctx *vmbus_msg_hc; struct vmbus_pcpu_data vmbus_pcpu[MAXCPU]; - /* Rarely used fields */ + /* + * Rarely used fields + */ + device_t vmbus_dev; int vmbus_idtvec; uint32_t vmbus_flags; /* see VMBUS_FLAG_ */ + uint32_t vmbus_version; + uint32_t vmbus_gpadl; /* Shared memory for vmbus_{rx,tx}_evtflags */ void *vmbus_evtflags; @@ -89,6 +100,9 @@ struct vmbus_softc { uint32_t vmbus_scan_chcnt; #define VMBUS_SCAN_CHCNT_DONE 0x80000000 uint32_t vmbus_scan_devcnt; + + struct mtx vmbus_chlist_lock; + TAILQ_HEAD(, hv_vmbus_channel) vmbus_chlist; }; #define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */ @@ -138,4 +152,6 @@ void vmbus_msghc_reset(struct vmbus_msghc *, size_t); void vmbus_scan_done(struct vmbus_softc *); void vmbus_scan_newchan(struct vmbus_softc *); +uint32_t vmbus_gpadl_alloc(struct vmbus_softc *); + #endif /* !_VMBUS_VAR_H_ */ |