Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 May 2016 03:19:54 +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: r300102 - head/sys/dev/hyperv/vmbus
Message-ID:  <201605180319.u4I3JsRu000443@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Wed May 18 03:19:53 2016
New Revision: 300102
URL: https://svnweb.freebsd.org/changeset/base/300102

Log:
  hyperv/vmbus: Reduce the # of event loops by recording event flag count
  
  Use vmbus softc to save vmbus per-cpu data.  More stuffs will be moved
  into vmbus softc.
  
  MFC after:	1 week
  Sponsored by:	Microsoft OSTC
  Differential Revision:	https://reviews.freebsd.org/D6403

Added:
  head/sys/dev/hyperv/vmbus/vmbus_var.h   (contents, props changed)
Modified:
  head/sys/dev/hyperv/vmbus/hv_channel.c
  head/sys/dev/hyperv/vmbus/hv_connection.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c

Modified: head/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel.c	Wed May 18 02:59:46 2016	(r300101)
+++ head/sys/dev/hyperv/vmbus/hv_channel.c	Wed May 18 03:19:53 2016	(r300102)
@@ -42,7 +42,8 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
-#include "hv_vmbus_priv.h"
+#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
 
 static int 	vmbus_channel_create_gpadl_header(
 			/* must be phys and virt contiguous*/
@@ -199,6 +200,8 @@ hv_vmbus_channel_open(
 	new_channel->on_channel_callback = pfn_on_channel_callback;
 	new_channel->channel_callback_context = context;
 
+	vmbus_on_channel_open(new_channel);
+
 	new_channel->rxq = hv_vmbus_g_context.hv_event_queue[new_channel->target_cpu];
 	TASK_INIT(&new_channel->channel_task, 0, VmbusProcessChannelEvent, new_channel);
 

Modified: head/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c	Wed May 18 02:59:46 2016	(r300101)
+++ head/sys/dev/hyperv/vmbus/hv_connection.c	Wed May 18 03:19:53 2016	(r300102)
@@ -38,7 +38,8 @@
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
-#include "hv_vmbus_priv.h"
+#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
 
 /*
  * Globals
@@ -294,10 +295,10 @@ hv_vmbus_disconnect(void) {
 void
 hv_vmbus_on_events(int cpu)
 {
-	unsigned long *intr_page;
+	unsigned long *intr_flags;
 	hv_vmbus_synic_event_flags *event;
 	void *page_addr;
-	int page_cnt, pg;
+	int flag_cnt, f;
 
 	KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
 	    "cpu out of range!"));
@@ -307,13 +308,13 @@ hv_vmbus_on_events(int cpu)
 	    page_addr + HV_VMBUS_MESSAGE_SINT;
 	if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
 	    (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
-		page_cnt = HV_MAX_NUM_CHANNELS_SUPPORTED >>
+		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_page = hv_vmbus_g_connection.recv_interrupt_page;
+			intr_flags = hv_vmbus_g_connection.recv_interrupt_page;
 		else
 			return;
 	} else {
@@ -322,23 +323,23 @@ hv_vmbus_on_events(int cpu)
 		 * checked directly to get the id of the channel
 		 * that has the pending interrupt.
 		 */
-		page_cnt = HV_EVENT_FLAGS_ULONG_COUNT;
-		intr_page = event->flagsul;
+		flag_cnt = VMBUS_PCPU_GET(event_flag_cnt, cpu);
+		intr_flags = event->flagsul;
 	}
 
 	/*
 	 * Check events
 	 */
-	for (pg = 0; pg < page_cnt; pg++) {
+	for (f = 0; f < flag_cnt; f++) {
 		uint32_t rel_id_base;
 		int bit;
 
-		if (intr_page[pg] == 0)
+		if (intr_flags[f] == 0)
 			continue;
 
-		rel_id_base = pg << HV_CHANNEL_ULONG_SHIFT;
+		rel_id_base = f << HV_CHANNEL_ULONG_SHIFT;
 		for (bit = 0; bit < HV_CHANNEL_ULONG_LEN; bit++) {
-			if (atomic_testandclear_long(&intr_page[pg], bit)) {
+			if (atomic_testandclear_long(&intr_flags[f], bit)) {
 				struct hv_vmbus_channel *channel;
 				uint32_t rel_id;
 
@@ -412,3 +413,30 @@ hv_vmbus_set_event(hv_vmbus_channel *cha
 
 	return (ret);
 }
+
+void
+vmbus_on_channel_open(const struct hv_vmbus_channel *chan)
+{
+	volatile int *flag_cnt_ptr;
+	int flag_cnt;
+
+	flag_cnt = (chan->offer_msg.child_rel_id / HV_CHANNEL_ULONG_LEN) + 1;
+	flag_cnt_ptr = VMBUS_PCPU_PTR(event_flag_cnt, chan->target_cpu);
+
+	for (;;) {
+		int old_flag_cnt;
+
+		old_flag_cnt = *flag_cnt_ptr;
+		if (old_flag_cnt >= flag_cnt)
+			break;
+		if (atomic_cmpset_int(flag_cnt_ptr, old_flag_cnt, flag_cnt)) {
+			if (bootverbose) {
+				printf("VMBUS: channel%u update "
+				    "cpu%d flag_cnt to %d\n",
+				    chan->offer_msg.child_rel_id,
+				    chan->target_cpu, flag_cnt);
+			}
+			break;
+		}
+	}
+}

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Wed May 18 02:59:46 2016	(r300101)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Wed May 18 03:19:53 2016	(r300102)
@@ -60,11 +60,14 @@ __FBSDID("$FreeBSD$");
 #include <x86/apicvar.h>
 
 #include <dev/hyperv/include/hyperv.h>
-#include "hv_vmbus_priv.h"
+#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
 
 #include <contrib/dev/acpica/include/acpi.h>
 #include "acpi_if.h"
 
+struct vmbus_softc	*vmbus_sc;
+
 static device_t vmbus_devp;
 static int vmbus_inited;
 static hv_setup_args setup_args; /* only CPU 0 supported at this time */
@@ -517,7 +520,9 @@ vmbus_attach(device_t dev)
 {
 	if(bootverbose)
 		device_printf(dev, "VMBUS: attach dev: %p\n", dev);
+
 	vmbus_devp = dev;
+	vmbus_sc = device_get_softc(dev);
 
 #ifndef EARLY_AP_STARTUP
 	/* 
@@ -537,7 +542,7 @@ vmbus_attach(device_t dev)
 static void
 vmbus_init(void)
 {
-	if (vm_guest != VM_GUEST_HV)
+	if (vm_guest != VM_GUEST_HV || vmbus_get_softc() == NULL)
 		return;
 
 #ifndef EARLY_AP_STARTUP
@@ -646,9 +651,11 @@ static device_method_t vmbus_methods[] =
 
 	{ 0, 0 } };
 
-static char driver_name[] = "vmbus";
-static driver_t vmbus_driver = { driver_name, vmbus_methods,0, };
-
+static driver_t vmbus_driver = {
+	"vmbus",
+	vmbus_methods,
+	sizeof(struct vmbus_softc)
+};
 
 devclass_t vmbus_devclass;
 

Added: head/sys/dev/hyperv/vmbus/vmbus_var.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/hyperv/vmbus/vmbus_var.h	Wed May 18 03:19:53 2016	(r300102)
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMBUS_VAR_H_
+#define _VMBUS_VAR_H_
+
+#include <sys/param.h>
+
+struct vmbus_pcpu_data {
+	int		event_flag_cnt;	/* # of event flags */
+} __aligned(CACHE_LINE_SIZE);
+
+struct vmbus_softc {
+	struct vmbus_pcpu_data	vmbus_pcpu[MAXCPU];
+};
+
+extern struct vmbus_softc	*vmbus_sc;
+
+static __inline struct vmbus_softc *
+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
+
+void	vmbus_on_channel_open(const struct hv_vmbus_channel *);
+
+#endif	/* !_VMBUS_VAR_H_ */



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