Author: sephe
Date: Wed Jun  8 05:34:22 2016
New Revision: 301583
URL: https://svnweb.freebsd.org/changeset/base/301583

Log:
  hyperv/vmbus: Busdma-fy MNF and event flags.
  
  MFC after:    1 week
  Sponsored by: Microsoft OSTC
  Differential Revision:        https://reviews.freebsd.org/D6744

Modified:
  head/sys/dev/hyperv/vmbus/hv_channel.c
  head/sys/dev/hyperv/vmbus/hv_connection.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  head/sys/dev/hyperv/vmbus/vmbus.c
  head/sys/dev/hyperv/vmbus/vmbus_var.h

Modified: head/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel.c      Wed Jun  8 05:32:39 2016        
(r301582)
+++ head/sys/dev/hyperv/vmbus/hv_channel.c      Wed Jun  8 05:34:22 2016        
(r301583)
@@ -62,17 +62,16 @@ static void VmbusProcessChannelEvent(voi
 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);

Modified: head/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c   Wed Jun  8 05:32:39 2016        
(r301582)
+++ head/sys/dev/hyperv/vmbus/hv_connection.c   Wed Jun  8 05:34:22 2016        
(r301583)
@@ -74,8 +74,8 @@ hv_vmbus_get_next_version(uint32_t curre
  * 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_chan
        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_chan
  * 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,
 }
 
 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, 
 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);

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Wed Jun  8 05:32:39 2016        
(r301582)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Wed Jun  8 05:34:22 2016        
(r301583)
@@ -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);

Modified: head/sys/dev/hyperv/vmbus/vmbus.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus.c   Wed Jun  8 05:32:39 2016        
(r301582)
+++ head/sys/dev/hyperv/vmbus/vmbus.c   Wed Jun  8 05:34:22 2016        
(r301583)
@@ -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;
 

Modified: head/sys/dev/hyperv/vmbus/vmbus_var.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_var.h       Wed Jun  8 05:32:39 2016        
(r301582)
+++ head/sys/dev/hyperv/vmbus/vmbus_var.h       Wed Jun  8 05:34:22 2016        
(r301583)
@@ -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 */
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to