summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-10-11 07:50:09 +0000
committersephe <sephe@FreeBSD.org>2016-10-11 07:50:09 +0000
commita539868648bd2f351694b90b22c3a25f97881c8d (patch)
tree80f2141d4bbdb9ab911474ff0d6e2837b21ba3f1
parentb03d921dcd6e7e62f6e1a5c692e7ad4240a0bd17 (diff)
downloadFreeBSD-src-a539868648bd2f351694b90b22c3a25f97881c8d.zip
FreeBSD-src-a539868648bd2f351694b90b22c3a25f97881c8d.tar.gz
MFC 302723,302726,302731
302723 hyperv: All Hypercall parameters have same alignment requirement. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7086 302726 hyperv: Signal event input parameter is shared w/ MNF Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7087 302731 hyperv/vmbus: Reorganize MNF event sending. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7088
-rw-r--r--sys/dev/hyperv/include/hyperv.h9
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel.c31
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c26
-rw-r--r--sys/dev/hyperv/vmbus/hyperv.c4
-rw-r--r--sys/dev/hyperv/vmbus/hyperv_reg.h29
-rw-r--r--sys/dev/hyperv/vmbus/hyperv_var.h2
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c5
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_reg.h28
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h2
9 files changed, 89 insertions, 47 deletions
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index d9e645a..1e7ae87 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -523,12 +523,13 @@ typedef struct hv_vmbus_channel {
hv_vmbus_channel_state state;
uint32_t ch_flags; /* VMBUS_CHAN_FLAG_ */
uint32_t ch_id; /* channel id */
+
/*
* These are based on the offer_msg.monitor_id.
* Save it here for easy access.
*/
- uint8_t monitor_group;
- uint8_t monitor_bit;
+ int ch_montrig_idx; /* MNF trig index */
+ uint32_t ch_montrig_mask;/* MNF trig mask */
uint32_t ring_buffer_gpadl_handle;
/*
@@ -551,8 +552,8 @@ typedef struct hv_vmbus_channel {
hv_vmbus_pfn_channel_callback on_channel_callback;
void* channel_callback_context;
- struct hypercall_sigevt_in *ch_sigevt;
- struct hyperv_dma ch_sigevt_dma;
+ struct hyperv_mon_param *ch_monprm;
+ struct hyperv_dma ch_monprm_dma;
/*
* From Win8, this field specifies the target virtual process
diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c
index 6667e63..8552e14 100644
--- a/sys/dev/hyperv/vmbus/hv_channel.c
+++ b/sys/dev/hyperv/vmbus/hv_channel.c
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#include <dev/hyperv/vmbus/vmbus_reg.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
-static void vmbus_channel_set_event(hv_vmbus_channel* channel);
+static void vmbus_chan_send_event(hv_vmbus_channel* channel);
static void vmbus_chan_update_evtflagcnt(struct vmbus_softc *,
const struct hv_vmbus_channel *);
static void vmbus_chan_task(void *, int);
@@ -60,7 +60,7 @@ static void vmbus_chan_task_nobatch(void *, int);
* @brief Trigger an event notification on the specified channel
*/
static void
-vmbus_channel_set_event(hv_vmbus_channel *channel)
+vmbus_chan_send_event(hv_vmbus_channel *channel)
{
struct vmbus_softc *sc = channel->vmbus_sc;
uint32_t chanid = channel->ch_id;
@@ -69,16 +69,12 @@ vmbus_channel_set_event(hv_vmbus_channel *channel)
1UL << (chanid & VMBUS_EVTFLAG_MASK));
if (channel->ch_flags & VMBUS_CHAN_FLAG_HASMNF) {
- hv_vmbus_monitor_page *monitor_page;
-
- monitor_page = sc->vmbus_mnf2;
- synch_set_bit(channel->monitor_bit,
- (uint32_t *)&monitor_page->
- trigger_group[channel->monitor_group].u.pending);
+ atomic_set_int(
+ &sc->vmbus_mnf2->mnf_trigs[channel->ch_montrig_idx].mt_pending,
+ channel->ch_montrig_mask);
} else {
- hypercall_signal_event(channel->ch_sigevt_dma.hv_paddr);
+ hypercall_signal_event(channel->ch_monprm_dma.hv_paddr);
}
-
}
static int
@@ -622,9 +618,8 @@ hv_vmbus_channel_send_packet(
&need_sig);
/* TODO: We should determine if this is optional */
- if (ret == 0 && need_sig) {
- vmbus_channel_set_event(channel);
- }
+ if (ret == 0 && need_sig)
+ vmbus_chan_send_event(channel);
return (ret);
}
@@ -690,9 +685,8 @@ hv_vmbus_channel_send_packet_pagebuffer(
&need_sig);
/* TODO: We should determine if this is optional */
- if (ret == 0 && need_sig) {
- vmbus_channel_set_event(channel);
- }
+ if (ret == 0 && need_sig)
+ vmbus_chan_send_event(channel);
return (ret);
}
@@ -766,9 +760,8 @@ hv_vmbus_channel_send_packet_multipagebuffer(
&need_sig);
/* TODO: We should determine if this is optional */
- if (ret == 0 && need_sig) {
- vmbus_channel_set_event(channel);
- }
+ if (ret == 0 && need_sig)
+ vmbus_chan_send_event(channel);
return (ret);
}
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index 71cf0e0..78f9bc0 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -299,23 +299,29 @@ vmbus_channel_on_offer_internal(struct vmbus_softc *sc,
if (offer->monitor_allocated)
new_channel->ch_flags |= VMBUS_CHAN_FLAG_HASMNF;
- new_channel->ch_sigevt = hyperv_dmamem_alloc(
+ new_channel->ch_monprm = 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");
+ HYPERCALL_PARAM_ALIGN, 0, sizeof(struct hyperv_mon_param),
+ &new_channel->ch_monprm_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (new_channel->ch_monprm == NULL) {
+ device_printf(sc->vmbus_dev, "monprm 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;
+ new_channel->ch_monprm->mp_connid = VMBUS_CONNID_EVENT;
if (sc->vmbus_version != VMBUS_VERSION_WS2008)
- new_channel->ch_sigevt->hc_connid = offer->connection_id;
-
- new_channel->monitor_group = (uint8_t) offer->monitor_id / 32;
- new_channel->monitor_bit = (uint8_t) offer->monitor_id % 32;
+ new_channel->ch_monprm->mp_connid = offer->connection_id;
+
+ if (new_channel->ch_flags & VMBUS_CHAN_FLAG_HASMNF) {
+ new_channel->ch_montrig_idx =
+ offer->monitor_id / VMBUS_MONTRIG_LEN;
+ if (new_channel->ch_montrig_idx >= VMBUS_MONTRIGS_MAX)
+ panic("invalid monitor id %u", offer->monitor_id);
+ new_channel->ch_montrig_mask =
+ 1 << (offer->monitor_id % VMBUS_MONTRIG_LEN);
+ }
/* Select default cpu for this channel. */
vmbus_channel_select_defcpu(new_channel);
diff --git a/sys/dev/hyperv/vmbus/hyperv.c b/sys/dev/hyperv/vmbus/hyperv.c
index c2ad3519..c4f7c01 100644
--- a/sys/dev/hyperv/vmbus/hyperv.c
+++ b/sys/dev/hyperv/vmbus/hyperv.c
@@ -109,10 +109,10 @@ hypercall_post_message(bus_addr_t msg_paddr)
}
uint64_t
-hypercall_signal_event(bus_addr_t sigevt_paddr)
+hypercall_signal_event(bus_addr_t monprm_paddr)
{
return hypercall_md(hypercall_context.hc_addr,
- HYPERCALL_SIGNAL_EVENT, sigevt_paddr, 0);
+ HYPERCALL_SIGNAL_EVENT, monprm_paddr, 0);
}
int
diff --git a/sys/dev/hyperv/vmbus/hyperv_reg.h b/sys/dev/hyperv/vmbus/hyperv_reg.h
index 20f4810..0601374 100644
--- a/sys/dev/hyperv/vmbus/hyperv_reg.h
+++ b/sys/dev/hyperv/vmbus/hyperv_reg.h
@@ -133,6 +133,15 @@
#define CPUID_LEAF_HV_HWFEATURES 0x40000006
/*
+ * Hyper-V Monitor Notification Facility
+ */
+struct hyperv_mon_param {
+ uint32_t mp_connid;
+ uint16_t mp_evtflag_ofs;
+ uint16_t mp_rsvd;
+} __packed;
+
+/*
* Hyper-V message types
*/
#define HYPERV_MSGTYPE_NONE 0
@@ -153,13 +162,22 @@
/*
* Hypercall input parameters
*/
+#define HYPERCALL_PARAM_ALIGN 8
+#if 0
+/*
+ * XXX
+ * <<Hypervisor Top Level Functional Specification 4.0b>> requires
+ * input parameters size to be multiple of 8, however, many post
+ * message input parameters do _not_ meet this requirement.
+ */
+#define HYPERCALL_PARAM_SIZE_ALIGN 8
+#endif
/*
* HYPERCALL_POST_MESSAGE
*/
#define HYPERCALL_POSTMSGIN_DSIZE_MAX 240
#define HYPERCALL_POSTMSGIN_SIZE 256
-#define HYPERCALL_POSTMSGIN_ALIGN 8
struct hypercall_postmsg_in {
uint32_t hc_connid;
@@ -172,13 +190,8 @@ CTASSERT(sizeof(struct hypercall_postmsg_in) == HYPERCALL_POSTMSGIN_SIZE);
/*
* HYPERCALL_SIGNAL_EVENT
+ *
+ * struct hyperv_mon_param.
*/
-#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 4b48d32..5d86a29 100644
--- a/sys/dev/hyperv/vmbus/hyperv_var.h
+++ b/sys/dev/hyperv/vmbus/hyperv_var.h
@@ -41,6 +41,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);
+uint64_t hypercall_signal_event(bus_addr_t monprm_paddr);
#endif /* !_HYPERV_VAR_H_ */
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index cd0fd24..bdff867 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -130,7 +130,7 @@ vmbus_msghc_alloc(bus_dma_tag_t parent_dtag)
mh = malloc(sizeof(*mh), M_DEVBUF, M_WAITOK | M_ZERO);
mh->mh_inprm = hyperv_dmamem_alloc(parent_dtag,
- HYPERCALL_POSTMSGIN_ALIGN, 0, HYPERCALL_POSTMSGIN_SIZE,
+ HYPERCALL_PARAM_ALIGN, 0, HYPERCALL_POSTMSGIN_SIZE,
&mh->mh_inprm_dma, BUS_DMA_WAITOK);
if (mh->mh_inprm == NULL) {
free(mh, M_DEVBUF);
@@ -835,7 +835,8 @@ vmbus_dma_alloc(struct vmbus_softc *sc)
return ENOMEM;
sc->vmbus_mnf2 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
- PAGE_SIZE, &sc->vmbus_mnf2_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ sizeof(struct vmbus_mnf), &sc->vmbus_mnf2_dma,
+ BUS_DMA_WAITOK | BUS_DMA_ZERO);
if (sc->vmbus_mnf2 == NULL)
return ENOMEM;
diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h
index ec23cdf..8719633 100644
--- a/sys/dev/hyperv/vmbus/vmbus_reg.h
+++ b/sys/dev/hyperv/vmbus/vmbus_reg.h
@@ -72,6 +72,34 @@ struct vmbus_evtflags {
CTASSERT(sizeof(struct vmbus_evtflags) == VMBUS_EVTFLAGS_SIZE);
/*
+ * Hyper-V Monitor Notification Facility
+ */
+
+struct vmbus_mon_trig {
+ uint32_t mt_pending;
+ uint32_t mt_armed;
+} __packed;
+
+#define VMBUS_MONTRIGS_MAX 4
+#define VMBUS_MONTRIG_LEN 32
+
+struct vmbus_mnf {
+ uint32_t mnf_state;
+ uint32_t mnf_rsvd1;
+
+ struct vmbus_mon_trig mnf_trigs[VMBUS_MONTRIGS_MAX];
+ uint8_t mnf_rsvd2[536];
+
+ uint16_t mnf_lat[VMBUS_MONTRIGS_MAX][VMBUS_MONTRIG_LEN];
+ uint8_t mnf_rsvd3[256];
+
+ struct hyperv_mon_param
+ mnf_param[VMBUS_MONTRIGS_MAX][VMBUS_MONTRIG_LEN];
+ uint8_t mnf_rsvd4[1984];
+} __packed;
+CTASSERT(sizeof(struct vmbus_mnf) == PAGE_SIZE);
+
+/*
* Channel
*/
diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h
index f159835..0f04b1f 100644
--- a/sys/dev/hyperv/vmbus/vmbus_var.h
+++ b/sys/dev/hyperv/vmbus/vmbus_var.h
@@ -70,7 +70,7 @@ struct vmbus_softc {
void (*vmbus_event_proc)(struct vmbus_softc *, int);
u_long *vmbus_tx_evtflags;
/* event flags to host */
- void *vmbus_mnf2; /* monitored by host */
+ struct vmbus_mnf *vmbus_mnf2; /* monitored by host */
u_long *vmbus_rx_evtflags;
/* compat evtflgs from host */
OpenPOWER on IntegriCloud