diff options
-rw-r--r-- | sys/conf/files.amd64 | 1 | ||||
-rw-r--r-- | sys/conf/files.i386 | 1 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel.c | 96 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel_mgmt.c | 10 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_connection.c | 183 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 31 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus.c | 15 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_var.h | 2 | ||||
-rw-r--r-- | sys/modules/hyperv/vmbus/Makefile | 1 |
9 files changed, 110 insertions, 230 deletions
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index e92ca0f..64d2fd3 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -273,7 +273,6 @@ dev/hyperv/utilities/hv_timesync.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hv_channel.c optional hyperv dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv -dev/hyperv/vmbus/hv_connection.c optional hyperv dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv dev/hyperv/vmbus/hyperv.c optional hyperv dev/hyperv/vmbus/hyperv_busdma.c optional hyperv diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index ecfb367..028bac1 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -250,7 +250,6 @@ dev/hyperv/utilities/hv_timesync.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hv_channel.c optional hyperv dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv -dev/hyperv/vmbus/hv_connection.c optional hyperv dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv dev/hyperv/vmbus/hyperv.c optional hyperv dev/hyperv/vmbus/hyperv_busdma.c optional hyperv diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index 6bb46ed..1c84c4f 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$"); static void vmbus_channel_set_event(hv_vmbus_channel* channel); static void VmbusProcessChannelEvent(void* channel, int pending); +static void vmbus_chan_update_evtflagcnt(struct vmbus_softc *, + const struct hv_vmbus_channel *); /** * @brief Trigger an event notification on the specified channel @@ -207,7 +209,7 @@ hv_vmbus_channel_open( new_channel->on_channel_callback = pfn_on_channel_callback; new_channel->channel_callback_context = context; - vmbus_on_channel_open(new_channel); + vmbus_chan_update_evtflagcnt(sc, new_channel); new_channel->rxq = VMBUS_PCPU_GET(new_channel->vmbus_sc, event_tq, new_channel->target_cpu); @@ -883,3 +885,95 @@ VmbusProcessChannelEvent(void* context, int pending) } while (is_batched_reading && (bytes_to_read != 0)); } } + +static __inline void +vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags, + int flag_cnt) +{ + int f; + + for (f = 0; f < flag_cnt; ++f) { + uint32_t rel_id_base; + u_long flags; + int bit; + + if (event_flags[f] == 0) + continue; + + flags = atomic_swap_long(&event_flags[f], 0); + rel_id_base = f << VMBUS_EVTFLAG_SHIFT; + + while ((bit = ffsl(flags)) != 0) { + struct hv_vmbus_channel *channel; + uint32_t rel_id; + + --bit; /* NOTE: ffsl is 1-based */ + flags &= ~(1UL << bit); + + rel_id = rel_id_base + bit; + channel = sc->vmbus_chmap[rel_id]; + + /* if channel is closed or closing */ + if (channel == NULL || channel->rxq == NULL) + continue; + + if (channel->batched_reading) + hv_ring_buffer_read_begin(&channel->inbound); + taskqueue_enqueue(channel->rxq, &channel->channel_task); + } + } +} + +void +vmbus_event_proc(struct vmbus_softc *sc, int cpu) +{ + struct vmbus_evtflags *eventf; + + /* + * On Host with Win8 or above, the event page can be checked directly + * to get the id of the channel that has the pending interrupt. + */ + eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; + vmbus_event_flags_proc(sc, eventf->evt_flags, + VMBUS_PCPU_GET(sc, event_flags_cnt, cpu)); +} + +void +vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu) +{ + struct vmbus_evtflags *eventf; + + eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; + if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) { + vmbus_event_flags_proc(sc, sc->vmbus_rx_evtflags, + VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT); + } +} + +static void +vmbus_chan_update_evtflagcnt(struct vmbus_softc *sc, + const struct hv_vmbus_channel *chan) +{ + volatile int *flag_cnt_ptr; + int flag_cnt; + + flag_cnt = (chan->offer_msg.child_rel_id / VMBUS_EVTFLAG_LEN) + 1; + flag_cnt_ptr = VMBUS_PCPU_PTR(sc, event_flags_cnt, chan->target_cpu); + + for (;;) { + int old_flag_cnt; + + old_flag_cnt = *flag_cnt_ptr; + if (old_flag_cnt >= flag_cnt) + break; + if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) { + if (bootverbose) { + device_printf(sc->vmbus_dev, + "channel%u update cpu%d flag_cnt to %d\n", + chan->offer_msg.child_rel_id, + chan->target_cpu, flag_cnt); + } + break; + } + } +} diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c index efbe5d7..2f6545d 100644 --- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -126,7 +126,7 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) */ printf("VMBUS: got channel0 offer\n"); } else { - hv_vmbus_g_connection.channels[relid] = new_channel; + sc->vmbus_chmap[relid] = new_channel; } TAILQ_FOREACH(channel, &sc->vmbus_chlist, ch_link) { @@ -354,10 +354,10 @@ vmbus_channel_on_offer_rescind(struct vmbus_softc *sc, rescind->child_rel_id); } - channel = hv_vmbus_g_connection.channels[rescind->child_rel_id]; + channel = sc->vmbus_chmap[rescind->child_rel_id]; if (channel == NULL) return; - hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL; + sc->vmbus_chmap[rescind->child_rel_id] = NULL; taskqueue_enqueue(taskqueue_thread, &channel->ch_detach_task); } @@ -454,8 +454,8 @@ hv_vmbus_release_unattached_channels(struct vmbus_softc *sc) } hv_vmbus_free_vmbus_channel(channel); } - bzero(hv_vmbus_g_connection.channels, - sizeof(hv_vmbus_channel*) * VMBUS_CHAN_MAX); + bzero(sc->vmbus_chmap, + sizeof(struct hv_vmbus_channel *) * VMBUS_CHAN_MAX); mtx_unlock(&sc->vmbus_chlist_lock); } diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c deleted file mode 100644 index fc30e40..0000000 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ /dev/null @@ -1,183 +0,0 @@ -/*- - * Copyright (c) 2009-2012,2016 Microsoft Corp. - * Copyright (c) 2012 NetApp Inc. - * Copyright (c) 2012 Citrix Inc. - * 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/systm.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <machine/bus.h> -#include <machine/atomic.h> -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> - -#include <dev/hyperv/vmbus/hv_vmbus_priv.h> -#include <dev/hyperv/vmbus/hyperv_reg.h> -#include <dev/hyperv/vmbus/vmbus_reg.h> -#include <dev/hyperv/vmbus/vmbus_var.h> - -/* - * Globals - */ -hv_vmbus_connection hv_vmbus_g_connection = - { .connect_state = HV_DISCONNECTED }; - -/** - * Send a connect request on the partition service connection - */ -int -hv_vmbus_connect(struct vmbus_softc *sc) -{ - /** - * Make sure we are not connecting or connected - */ - if (hv_vmbus_g_connection.connect_state != HV_DISCONNECTED) { - return (-1); - } - - /** - * Initialize the vmbus connection - */ - hv_vmbus_g_connection.connect_state = HV_CONNECTING; - - hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) * - VMBUS_CHAN_MAX, M_DEVBUF, M_WAITOK | M_ZERO); - - hv_vmbus_g_connection.connect_state = HV_CONNECTED; - - return (0); -} - -/** - * Send a disconnect request on the partition service connection - */ -int -hv_vmbus_disconnect(void) -{ - - free(hv_vmbus_g_connection.channels, M_DEVBUF); - hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; - - return (0); -} - -static __inline void -vmbus_event_flags_proc(volatile u_long *event_flags, int flag_cnt) -{ - int f; - - for (f = 0; f < flag_cnt; ++f) { - uint32_t rel_id_base; - u_long flags; - int bit; - - if (event_flags[f] == 0) - continue; - - flags = atomic_swap_long(&event_flags[f], 0); - rel_id_base = f << VMBUS_EVTFLAG_SHIFT; - - while ((bit = ffsl(flags)) != 0) { - struct hv_vmbus_channel *channel; - uint32_t rel_id; - - --bit; /* NOTE: ffsl is 1-based */ - flags &= ~(1UL << bit); - - rel_id = rel_id_base + bit; - channel = hv_vmbus_g_connection.channels[rel_id]; - - /* if channel is closed or closing */ - if (channel == NULL || channel->rxq == NULL) - continue; - - if (channel->batched_reading) - hv_ring_buffer_read_begin(&channel->inbound); - taskqueue_enqueue(channel->rxq, &channel->channel_task); - } - } -} - -void -vmbus_event_proc(struct vmbus_softc *sc, int cpu) -{ - struct vmbus_evtflags *eventf; - - /* - * On Host with Win8 or above, the event page can be checked directly - * to get the id of the channel that has the pending interrupt. - */ - eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; - vmbus_event_flags_proc(eventf->evt_flags, - VMBUS_PCPU_GET(sc, event_flags_cnt, cpu)); -} - -void -vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu) -{ - struct vmbus_evtflags *eventf; - - eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; - if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) { - vmbus_event_flags_proc(sc->vmbus_rx_evtflags, - VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT); - } -} - -void -vmbus_on_channel_open(const struct hv_vmbus_channel *chan) -{ - volatile int *flag_cnt_ptr; - int flag_cnt; - - flag_cnt = (chan->offer_msg.child_rel_id / VMBUS_EVTFLAG_LEN) + 1; - flag_cnt_ptr = VMBUS_PCPU_PTR(chan->vmbus_sc, event_flags_cnt, - chan->target_cpu); - - for (;;) { - int old_flag_cnt; - - old_flag_cnt = *flag_cnt_ptr; - if (old_flag_cnt >= flag_cnt) - break; - if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) { - if (bootverbose) { - printf("VMBUS: channel%u update " - "cpu%d flag_cnt to %d\n", - chan->offer_msg.child_rel_id, - chan->target_cpu, flag_cnt); - } - break; - } - } -} diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 1dd5251..1cba8a7 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -97,25 +97,6 @@ typedef struct hv_vmbus_channel_packet_multipage_buffer { hv_vmbus_multipage_buffer range; } __packed hv_vmbus_channel_packet_multipage_buffer; -/* - * VM Bus connection states - */ -typedef enum { - HV_DISCONNECTED, - HV_CONNECTING, - HV_CONNECTED, - HV_DISCONNECTING -} hv_vmbus_connect_state; - -typedef struct { - hv_vmbus_connect_state connect_state; - - /** - * channel table for fast lookup through id. - */ - hv_vmbus_channel **channels; -} hv_vmbus_connection; - typedef union { uint32_t as_uint32_t; struct { @@ -177,12 +158,6 @@ typedef struct { uint8_t rsvd_z4[1984]; } hv_vmbus_monitor_page; -/** - * Global variables - */ - -extern hv_vmbus_connection hv_vmbus_g_connection; - /* * Private, VM Bus functions */ @@ -247,10 +222,4 @@ void hv_vmbus_child_device_register(struct vmbus_softc *, int hv_vmbus_child_device_unregister( struct hv_device *child_dev); -/** - * Connection interfaces - */ -int hv_vmbus_connect(struct vmbus_softc *); -int hv_vmbus_disconnect(void); - #endif /* __HYPERV_PRIV_H__ */ diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c index a2d807d..7e7439d 100644 --- a/sys/dev/hyperv/vmbus/vmbus.c +++ b/sys/dev/hyperv/vmbus/vmbus.c @@ -1212,6 +1212,9 @@ vmbus_doattach(struct vmbus_softc *sc) sc->vmbus_gpadl = VMBUS_GPADL_START; mtx_init(&sc->vmbus_chlist_lock, "vmbus chlist", NULL, MTX_DEF); TAILQ_INIT(&sc->vmbus_chlist); + sc->vmbus_chmap = malloc( + sizeof(struct hv_vmbus_channel *) * VMBUS_CHAN_MAX, M_DEVBUF, + M_WAITOK | M_ZERO); /* * Create context for "post message" Hypercalls @@ -1246,12 +1249,8 @@ vmbus_doattach(struct vmbus_softc *sc) sc->vmbus_flags |= VMBUS_FLAG_SYNIC; /* - * Connect to VMBus in the root partition + * Initialize vmbus, e.g. connect to Hypervisor. */ - ret = hv_vmbus_connect(sc); - if (ret != 0) - goto cleanup; - ret = vmbus_init(sc); if (ret != 0) goto cleanup; @@ -1281,7 +1280,9 @@ cleanup: vmbus_msghc_ctx_destroy(sc->vmbus_msg_hc); sc->vmbus_msg_hc = NULL; } + free(sc->vmbus_chmap, M_DEVBUF); mtx_destroy(&sc->vmbus_scan_lock); + mtx_destroy(&sc->vmbus_chlist_lock); return (ret); } @@ -1342,7 +1343,6 @@ vmbus_detach(device_t dev) hv_vmbus_release_unattached_channels(sc); vmbus_disconnect(sc); - hv_vmbus_disconnect(); if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) { sc->vmbus_flags &= ~VMBUS_FLAG_SYNIC; @@ -1357,7 +1357,10 @@ vmbus_detach(device_t dev) sc->vmbus_msg_hc = NULL; } + free(sc->vmbus_chmap, M_DEVBUF); mtx_destroy(&sc->vmbus_scan_lock); + mtx_destroy(&sc->vmbus_chlist_lock); + return (0); } diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h index 42a2b97..f159835 100644 --- a/sys/dev/hyperv/vmbus/vmbus_var.h +++ b/sys/dev/hyperv/vmbus/vmbus_var.h @@ -74,6 +74,7 @@ struct vmbus_softc { u_long *vmbus_rx_evtflags; /* compat evtflgs from host */ + struct hv_vmbus_channel **vmbus_chmap; struct vmbus_msghc_ctx *vmbus_msg_hc; struct vmbus_pcpu_data vmbus_pcpu[MAXCPU]; @@ -129,7 +130,6 @@ struct trapframe; struct vmbus_message; struct vmbus_msghc; -void vmbus_on_channel_open(const struct hv_vmbus_channel *); void vmbus_event_proc(struct vmbus_softc *, int); void vmbus_event_proc_compat(struct vmbus_softc *, int); void vmbus_handle_intr(struct trapframe *); diff --git a/sys/modules/hyperv/vmbus/Makefile b/sys/modules/hyperv/vmbus/Makefile index 89b0e74..c817cec 100644 --- a/sys/modules/hyperv/vmbus/Makefile +++ b/sys/modules/hyperv/vmbus/Makefile @@ -6,7 +6,6 @@ KMOD= hv_vmbus SRCS= hv_channel.c \ hv_channel_mgmt.c \ - hv_connection.c \ hv_ring_buffer.c \ hyperv.c \ hyperv_busdma.c \ |