Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 May 2016 03:41:37 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r300107 - head/sys/dev/hyperv/vmbus
Message-ID:  <201605180341.u4I3fbXx006924@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605180341.u4I3fbXx006924>