summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/vmbus
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-06-08 05:34:22 +0000
committersephe <sephe@FreeBSD.org>2016-06-08 05:34:22 +0000
commit1f0b9095a5874fad8aec0bbf0eeaff727a63e72b (patch)
treecd33fa4739518fcb1487f340404c818712b9d347 /sys/dev/hyperv/vmbus
parent7f608aeba98bd17fec002846907ff09fb14e9534 (diff)
downloadFreeBSD-src-1f0b9095a5874fad8aec0bbf0eeaff727a63e72b.zip
FreeBSD-src-1f0b9095a5874fad8aec0bbf0eeaff727a63e72b.tar.gz
hyperv/vmbus: Busdma-fy MNF and event flags.
MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6744
Diffstat (limited to 'sys/dev/hyperv/vmbus')
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel.c11
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c66
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h23
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c50
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_var.h16
5 files changed, 76 insertions, 90 deletions
diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c
index c1d415f..f3a23af 100644
--- a/sys/dev/hyperv/vmbus/hv_channel.c
+++ b/sys/dev/hyperv/vmbus/hv_channel.c
@@ -62,17 +62,16 @@ static void VmbusProcessChannelEvent(void* channel, int pending);
static void
vmbus_channel_set_event(hv_vmbus_channel *channel)
{
- hv_vmbus_monitor_page *monitor_page;
-
if (channel->offer_msg.monitor_allocated) {
+ struct vmbus_softc *sc = vmbus_get_softc();
+ hv_vmbus_monitor_page *monitor_page;
+
/* Each uint32_t represents 32 channels */
synch_set_bit((channel->offer_msg.child_rel_id & 31),
- ((uint32_t *)hv_vmbus_g_connection.send_interrupt_page
+ ((uint32_t *)sc->vmbus_tx_evtflags
+ ((channel->offer_msg.child_rel_id >> 5))));
- monitor_page = (hv_vmbus_monitor_page *)
- hv_vmbus_g_connection.monitor_page_2;
-
+ monitor_page = sc->vmbus_mnf2;
synch_set_bit(channel->monitor_bit,
(uint32_t *)&monitor_page->
trigger_group[channel->monitor_group].u.pending);
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index 8a0bb09..c1bf4a1 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -74,8 +74,8 @@ hv_vmbus_get_next_version(uint32_t current_ver)
* Negotiate the highest supported hypervisor version.
*/
static int
-hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
- uint32_t version)
+hv_vmbus_negotiate_version(struct vmbus_softc *sc,
+ hv_vmbus_channel_msg_info *msg_info, uint32_t version)
{
int ret = 0;
hv_vmbus_channel_initiate_contact *msg;
@@ -86,14 +86,9 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
msg->header.message_type = HV_CHANNEL_MESSAGE_INITIATED_CONTACT;
msg->vmbus_version_requested = version;
- msg->interrupt_page = hv_get_phys_addr(
- hv_vmbus_g_connection.interrupt_page);
-
- msg->monitor_page_1 = hv_get_phys_addr(
- hv_vmbus_g_connection.monitor_page_1);
-
- msg->monitor_page_2 = hv_get_phys_addr(
- hv_vmbus_g_connection.monitor_page_2);
+ msg->interrupt_page = sc->vmbus_evtflags_dma.hv_paddr;
+ msg->monitor_page_1 = sc->vmbus_mnf1_dma.hv_paddr;
+ msg->monitor_page_2 = sc->vmbus_mnf2_dma.hv_paddr;
/**
* Add to list before we send the request since we may receive the
@@ -150,7 +145,7 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
* Send a connect request on the partition service connection
*/
int
-hv_vmbus_connect(void)
+hv_vmbus_connect(struct vmbus_softc *sc)
{
int ret = 0;
uint32_t version;
@@ -176,34 +171,6 @@ hv_vmbus_connect(void)
mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel",
NULL, MTX_DEF);
- /**
- * Setup the vmbus event connection for channel interrupt abstraction
- * stuff
- */
- hv_vmbus_g_connection.interrupt_page = malloc(
- PAGE_SIZE, M_DEVBUF,
- M_WAITOK | M_ZERO);
-
- hv_vmbus_g_connection.recv_interrupt_page =
- hv_vmbus_g_connection.interrupt_page;
-
- hv_vmbus_g_connection.send_interrupt_page =
- ((uint8_t *) hv_vmbus_g_connection.interrupt_page +
- (PAGE_SIZE >> 1));
-
- /**
- * Set up the monitor notification facility. The 1st page for
- * parent->child and the 2nd page for child->parent
- */
- hv_vmbus_g_connection.monitor_page_1 = malloc(
- PAGE_SIZE,
- M_DEVBUF,
- M_WAITOK | M_ZERO);
- hv_vmbus_g_connection.monitor_page_2 = malloc(
- PAGE_SIZE,
- M_DEVBUF,
- M_WAITOK | M_ZERO);
-
msg_info = (hv_vmbus_channel_msg_info*)
malloc(sizeof(hv_vmbus_channel_msg_info) +
sizeof(hv_vmbus_channel_initiate_contact),
@@ -217,7 +184,7 @@ hv_vmbus_connect(void)
version = HV_VMBUS_VERSION_CURRENT;
do {
- ret = hv_vmbus_negotiate_version(msg_info, version);
+ ret = hv_vmbus_negotiate_version(sc, msg_info, version);
if (ret == EWOULDBLOCK) {
/*
* We timed out.
@@ -251,14 +218,6 @@ hv_vmbus_connect(void)
mtx_destroy(&hv_vmbus_g_connection.channel_lock);
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
- if (hv_vmbus_g_connection.interrupt_page != NULL) {
- free(hv_vmbus_g_connection.interrupt_page, M_DEVBUF);
- hv_vmbus_g_connection.interrupt_page = NULL;
- }
-
- free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF);
- free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF);
-
if (msg_info) {
sema_destroy(&msg_info->wait_sema);
free(msg_info, M_DEVBUF);
@@ -281,8 +240,6 @@ hv_vmbus_disconnect(void)
ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload));
- free(hv_vmbus_g_connection.interrupt_page, M_DEVBUF);
-
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
free(hv_vmbus_g_connection.channels, M_DEVBUF);
@@ -343,14 +300,13 @@ vmbus_event_proc(struct vmbus_softc *sc, int cpu)
}
void
-vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu)
+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(
- hv_vmbus_g_connection.recv_interrupt_page,
+ vmbus_event_flags_proc(sc->vmbus_rx_evtflags,
VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT);
}
}
@@ -395,14 +351,14 @@ int hv_vmbus_post_message(void *buffer, size_t bufferLen)
int
hv_vmbus_set_event(hv_vmbus_channel *channel)
{
+ struct vmbus_softc *sc = vmbus_get_softc();
int ret = 0;
uint32_t child_rel_id = channel->offer_msg.child_rel_id;
/* Each uint32_t represents 32 channels */
synch_set_bit(child_rel_id & 31,
- (((uint32_t *)hv_vmbus_g_connection.send_interrupt_page
- + (child_rel_id >> 5))));
+ (((uint32_t *)sc->vmbus_tx_evtflags + (child_rel_id >> 5))));
ret = hv_vmbus_signal_event(channel->signal_event_param);
return (ret);
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index f7ea849..0008226 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -244,25 +244,7 @@ typedef enum {
typedef struct {
hv_vmbus_connect_state connect_state;
uint32_t next_gpadl_handle;
- /**
- * Represents channel interrupts. Each bit position
- * represents a channel.
- * When a channel sends an interrupt via VMBUS, it
- * finds its bit in the send_interrupt_page, set it and
- * calls Hv to generate a port event. The other end
- * receives the port event and parse the
- * recv_interrupt_page to see which bit is set
- */
- void *interrupt_page;
- void *send_interrupt_page;
- void *recv_interrupt_page;
- /*
- * 2 pages - 1st page for parent->child
- * notification and 2nd is child->parent
- * notification
- */
- void *monitor_page_1;
- void *monitor_page_2;
+
TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor;
struct mtx channel_msg_lock;
/**
@@ -440,7 +422,8 @@ int hv_vmbus_child_device_unregister(
/**
* Connection interfaces
*/
-int hv_vmbus_connect(void);
+struct vmbus_softc;
+int hv_vmbus_connect(struct vmbus_softc *);
int hv_vmbus_disconnect(void);
int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(hv_vmbus_channel *channel);
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index bd63067..6fadee7 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -309,30 +309,50 @@ vmbus_synic_teardown(void *arg)
static int
vmbus_dma_alloc(struct vmbus_softc *sc)
{
+ bus_dma_tag_t parent_dtag;
+ uint8_t *evtflags;
int cpu;
+ parent_dtag = bus_get_dma_tag(sc->vmbus_dev);
CPU_FOREACH(cpu) {
void *ptr;
/*
* Per-cpu messages and event flags.
*/
- ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
- PAGE_SIZE, 0, PAGE_SIZE,
- VMBUS_PCPU_PTR(sc, message_dma, cpu),
+ ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+ PAGE_SIZE, VMBUS_PCPU_PTR(sc, message_dma, cpu),
BUS_DMA_WAITOK | BUS_DMA_ZERO);
if (ptr == NULL)
return ENOMEM;
VMBUS_PCPU_GET(sc, message, cpu) = ptr;
- ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
- PAGE_SIZE, 0, PAGE_SIZE,
- VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
+ ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+ PAGE_SIZE, VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
BUS_DMA_WAITOK | BUS_DMA_ZERO);
if (ptr == NULL)
return ENOMEM;
VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr;
}
+
+ evtflags = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+ PAGE_SIZE, &sc->vmbus_evtflags_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (evtflags == NULL)
+ return ENOMEM;
+ sc->vmbus_rx_evtflags = (u_long *)evtflags;
+ sc->vmbus_tx_evtflags = evtflags + (PAGE_SIZE / 2);
+ sc->vmbus_evtflags = evtflags;
+
+ sc->vmbus_mnf1 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
+ PAGE_SIZE, &sc->vmbus_mnf1_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (sc->vmbus_mnf1 == NULL)
+ 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);
+ if (sc->vmbus_mnf2 == NULL)
+ return ENOMEM;
+
return 0;
}
@@ -341,6 +361,21 @@ vmbus_dma_free(struct vmbus_softc *sc)
{
int cpu;
+ if (sc->vmbus_evtflags != NULL) {
+ hyperv_dmamem_free(&sc->vmbus_evtflags_dma, sc->vmbus_evtflags);
+ sc->vmbus_evtflags = NULL;
+ sc->vmbus_rx_evtflags = NULL;
+ sc->vmbus_tx_evtflags = NULL;
+ }
+ if (sc->vmbus_mnf1 != NULL) {
+ hyperv_dmamem_free(&sc->vmbus_mnf1_dma, sc->vmbus_mnf1);
+ sc->vmbus_mnf1 = NULL;
+ }
+ if (sc->vmbus_mnf2 != NULL) {
+ hyperv_dmamem_free(&sc->vmbus_mnf2_dma, sc->vmbus_mnf2);
+ sc->vmbus_mnf2 = NULL;
+ }
+
CPU_FOREACH(cpu) {
if (VMBUS_PCPU_GET(sc, message, cpu) != NULL) {
hyperv_dmamem_free(
@@ -609,8 +644,7 @@ vmbus_bus_init(void)
/*
* Connect to VMBus in the root partition
*/
- ret = hv_vmbus_connect();
-
+ ret = hv_vmbus_connect(sc);
if (ret != 0)
goto cleanup;
diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h
index 440f4d3..3f69d9f 100644
--- a/sys/dev/hyperv/vmbus/vmbus_var.h
+++ b/sys/dev/hyperv/vmbus/vmbus_var.h
@@ -51,7 +51,7 @@ struct vmbus_pcpu_data {
struct vmbus_message *message; /* shared messages */
uint32_t vcpuid; /* virtual cpuid */
int event_flags_cnt;/* # of event flags */
- struct vmbus_evtflags *event_flags; /* shared event flags */
+ struct vmbus_evtflags *event_flags; /* event flags from host */
/* Rarely used fields */
struct hyperv_dma message_dma; /* busdma glue */
@@ -63,12 +63,26 @@ struct vmbus_pcpu_data {
struct vmbus_softc {
void (*vmbus_event_proc)(struct vmbus_softc *, int);
+ void *vmbus_tx_evtflags;
+ /* event flags to host */
+ void *vmbus_mnf2; /* monitored by host */
+
+ u_long *vmbus_rx_evtflags;
+ /* compat evtflgs from host */
struct vmbus_pcpu_data vmbus_pcpu[MAXCPU];
/* Rarely used fields */
device_t vmbus_dev;
int vmbus_idtvec;
uint32_t vmbus_flags; /* see VMBUS_FLAG_ */
+
+ /* Shared memory for vmbus_{rx,tx}_evtflags */
+ void *vmbus_evtflags;
+ struct hyperv_dma vmbus_evtflags_dma;
+
+ void *vmbus_mnf1; /* monitored by VM, unused */
+ struct hyperv_dma vmbus_mnf1_dma;
+ struct hyperv_dma vmbus_mnf2_dma;
};
#define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */
OpenPOWER on IntegriCloud