diff options
author | sephe <sephe@FreeBSD.org> | 2016-06-08 05:34:22 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-06-08 05:34:22 +0000 |
commit | 1f0b9095a5874fad8aec0bbf0eeaff727a63e72b (patch) | |
tree | cd33fa4739518fcb1487f340404c818712b9d347 /sys/dev/hyperv/vmbus | |
parent | 7f608aeba98bd17fec002846907ff09fb14e9534 (diff) | |
download | FreeBSD-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.c | 11 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_connection.c | 66 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 23 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus.c | 50 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_var.h | 16 |
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 */ |