Author: sephe
Date: Wed May 18 03:41:37 2016
New Revision: 300107
URL: https://svnweb.freebsd.org/changeset/base/300107

Log:
  hyperv/vmbus: Avoid two unnecessary protocol checks on isr handling path
  
  MFC after:    1 week
  Sponsored by: Microsoft OSTC
  Differential Revision:        https://reviews.freebsd.org/D6405

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

Modified: head/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c   Wed May 18 03:34:02 2016        
(r300106)
+++ head/sys/dev/hyperv/vmbus/hv_connection.c   Wed May 18 03:41:37 2016        
(r300107)
@@ -289,56 +289,20 @@ hv_vmbus_disconnect(void) {
        return (ret);
 }
 
-/**
- * Handler for events
- */
-void
-hv_vmbus_on_events(int cpu)
+static __inline void
+vmbus_event_flags_proc(unsigned long *event_flags, int flag_cnt)
 {
-       unsigned long *intr_flags;
-       hv_vmbus_synic_event_flags *event;
-       void *page_addr;
-       int flag_cnt, f;
-
-       KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
-           "cpu out of range!"));
-
-       page_addr = hv_vmbus_g_context.syn_ic_event_page[cpu];
-       event = (hv_vmbus_synic_event_flags *)
-           page_addr + HV_VMBUS_MESSAGE_SINT;
-       if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
-           (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
-               flag_cnt = HV_MAX_NUM_CHANNELS_SUPPORTED >>
-                   HV_CHANNEL_ULONG_SHIFT;
-               /*
-                * receive size is 1/2 page and divide that by 4 bytes
-                */
-               if (atomic_testandclear_int(&event->flags32[0], 0))
-                       intr_flags = hv_vmbus_g_connection.recv_interrupt_page;
-               else
-                       return;
-       } else {
-               /*
-                * On Host with Win8 or above, the event page can be
-                * checked directly to get the id of the channel
-                * that has the pending interrupt.
-                */
-               flag_cnt = VMBUS_PCPU_GET(event_flag_cnt, cpu);
-               intr_flags = event->flagsul;
-       }
+       int f;
 
-       /*
-        * Check events
-        */
-       for (f = 0; f < flag_cnt; f++) {
+       for (f = 0; f < flag_cnt; ++f) {
                uint32_t rel_id_base;
                unsigned long flags;
                int bit;
 
-               if (intr_flags[f] == 0)
+               if (event_flags[f] == 0)
                        continue;
 
-               flags = atomic_swap_long(&intr_flags[f], 0);
+               flags = atomic_swap_long(&event_flags[f], 0);
                rel_id_base = f << HV_CHANNEL_ULONG_SHIFT;
 
                while ((bit = ffsl(flags)) != 0) {
@@ -362,6 +326,37 @@ hv_vmbus_on_events(int cpu)
        }
 }
 
+void
+vmbus_event_proc(struct vmbus_softc *sc, int cpu)
+{
+       hv_vmbus_synic_event_flags *event;
+
+       event = ((hv_vmbus_synic_event_flags *)
+           hv_vmbus_g_context.syn_ic_event_page[cpu]) + HV_VMBUS_MESSAGE_SINT;
+
+       /*
+        * On Host with Win8 or above, the event page can be checked directly
+        * to get the id of the channel that has the pending interrupt.
+        */
+       vmbus_event_flags_proc(event->flagsul,
+           VMBUS_SC_PCPU_GET(sc, event_flag_cnt, cpu));
+}
+
+void
+vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu)
+{
+       hv_vmbus_synic_event_flags *event;
+
+       event = ((hv_vmbus_synic_event_flags *)
+           hv_vmbus_g_context.syn_ic_event_page[cpu]) + HV_VMBUS_MESSAGE_SINT;
+
+       if (atomic_testandclear_int(&event->flags32[0], 0)) {
+               vmbus_event_flags_proc(
+                   hv_vmbus_g_connection.recv_interrupt_page,
+                   HV_MAX_NUM_CHANNELS_SUPPORTED >> HV_CHANNEL_ULONG_SHIFT);
+       }
+}
+
 /**
  * Send a msg on the vmbus's message connection
  */

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c    Wed May 18 03:34:02 
2016        (r300106)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c    Wed May 18 03:41:37 
2016        (r300107)
@@ -146,6 +146,7 @@ handled:
 static inline int
 hv_vmbus_isr(struct trapframe *frame)
 {
+       struct vmbus_softc *sc = vmbus_get_softc();
        int                             cpu;
        hv_vmbus_message*               msg;
        void*                           page_addr;
@@ -157,8 +158,7 @@ hv_vmbus_isr(struct trapframe *frame)
         * before checking for messages. This is the way they do it
         * in Windows when running as a guest in Hyper-V
         */
-
-       hv_vmbus_on_events(cpu);
+       sc->vmbus_event_proc(sc, cpu);
 
        /* Check if there are actual msgs to be process */
        page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
@@ -388,6 +388,7 @@ extern inthand_t IDTVEC(hv_vmbus_callbac
 static int
 vmbus_bus_init(void)
 {
+       struct vmbus_softc *sc;
        int i, j, n, ret;
        char buf[MAXCOMLEN + 1];
        cpuset_t cpu_mask;
@@ -396,6 +397,7 @@ vmbus_bus_init(void)
                return (0);
 
        vmbus_inited = 1;
+       sc = vmbus_get_softc();
 
        ret = hv_vmbus_init();
 
@@ -481,6 +483,12 @@ vmbus_bus_init(void)
        if (ret != 0)
                goto cleanup1;
 
+       if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 ||
+           hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)
+               sc->vmbus_event_proc = vmbus_event_proc_compat;
+       else
+               sc->vmbus_event_proc = vmbus_event_proc;
+
        hv_vmbus_request_channel_offers();
 
        vmbus_scan();
@@ -515,6 +523,11 @@ vmbus_bus_init(void)
        return (ret);
 }
 
+static void
+vmbus_event_proc_dummy(struct vmbus_softc *sc __unused, int cpu __unused)
+{
+}
+
 static int
 vmbus_attach(device_t dev)
 {
@@ -524,6 +537,13 @@ vmbus_attach(device_t dev)
        vmbus_devp = dev;
        vmbus_sc = device_get_softc(dev);
 
+       /*
+        * Event processing logic will be configured:
+        * - After the vmbus protocol version negotiation.
+        * - Before we request channel offers.
+        */
+       vmbus_sc->vmbus_event_proc = vmbus_event_proc_dummy;
+
 #ifndef EARLY_AP_STARTUP
        /* 
         * If the system has already booted and thread

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Wed May 18 03:34:02 2016        
(r300106)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Wed May 18 03:41:37 2016        
(r300107)
@@ -753,7 +753,6 @@ int                 hv_vmbus_connect(void);
 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);
-void                   hv_vmbus_on_events(int cpu);
 
 /**
  * Event Timer interfaces

Modified: head/sys/dev/hyperv/vmbus/vmbus_var.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_var.h       Wed May 18 03:34:02 2016        
(r300106)
+++ head/sys/dev/hyperv/vmbus/vmbus_var.h       Wed May 18 03:41:37 2016        
(r300107)
@@ -36,6 +36,7 @@ struct vmbus_pcpu_data {
 } __aligned(CACHE_LINE_SIZE);
 
 struct vmbus_softc {
+       void                    (*vmbus_event_proc)(struct vmbus_softc *, int);
        struct vmbus_pcpu_data  vmbus_pcpu[MAXCPU];
 };
 
@@ -47,11 +48,15 @@ vmbus_get_softc(void)
        return vmbus_sc;
 }
 
-#define VMBUS_PCPU_GET(field, cpu)     \
-       (vmbus_get_softc())->vmbus_pcpu[cpu].field
-#define VMBUS_PCPU_PTR(field, cpu)     \
-       &(vmbus_get_softc())->vmbus_pcpu[cpu].field
+#define VMBUS_SC_PCPU_GET(sc, field, cpu)      (sc)->vmbus_pcpu[(cpu)].field
+#define VMBUS_SC_PCPU_PTR(sc, field, cpu)      &(sc)->vmbus_pcpu[(cpu)].field
+#define VMBUS_PCPU_GET(field, cpu)             \
+       VMBUS_SC_PCPU_GET(vmbus_get_softc(), field, (cpu))
+#define VMBUS_PCPU_PTR(field, cpu)             \
+       VMBUS_SC_PCPU_PTR(vmbus_get_softc(), field, (cpu))
 
 void   vmbus_on_channel_open(const struct hv_vmbus_channel *);
+void   vmbus_event_proc(struct vmbus_softc *, int);
+void   vmbus_event_proc_compat(struct vmbus_softc *, int);
 
 #endif /* !_VMBUS_VAR_H_ */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to