summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-10-14 08:02:37 +0000
committersephe <sephe@FreeBSD.org>2016-10-14 08:02:37 +0000
commit5691021e808c20e7a770942b04bdb9e039d2f624 (patch)
tree8de1d9c8074cfd3e4e05d8575346267569092ac1 /sys/dev/hyperv
parent56da3ec17e37a6540c26f6be524c4c541e122690 (diff)
downloadFreeBSD-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.h40
-rw-r--r--sys/dev/hyperv/include/hyperv_busdma.h4
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c30
-rw-r--r--sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c11
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel.c18
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c206
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c26
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h118
-rw-r--r--sys/dev/hyperv/vmbus/hyperv.c35
-rw-r--r--sys/dev/hyperv/vmbus/hyperv_reg.h12
-rw-r--r--sys/dev/hyperv/vmbus/hyperv_var.h1
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c92
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_if.m37
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_reg.h26
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h18
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_ */
OpenPOWER on IntegriCloud