Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Jun 2016 03:04:17 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r301946 - in stable/10/sys/dev/hyperv: include utilities vmbus
Message-ID:  <201606160304.u5G34HKN047592@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Jun 16 03:04:16 2016
New Revision: 301946
URL: https://svnweb.freebsd.org/changeset/base/301946

Log:
  MFC 297142,297143,297176,297177,297178,297221
  
  297142
      hyperv: Factor out snprinf_hv_guid()
  
      Submitted by:       Ju Sun <junsu microsoft com>
      Reviewed by:        Dexuan Cui <decui microsoft com>, sephe
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5651
  
  297143
      hyperv/vmbus: Implement bus_child_pnpinfo_str method
  
      Submitted by:       Jun Su <junsu microsoft com>
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5669
  
  297176
      hyperv/evttimer: Use an independent message slot so that it can work
  
      Using the same message slot as the other types of the messages has
      the side effect that the event timer message could be deferred to
      the swi threads to run (lacking of trapframe and the original code
      didn't even handle that, so the event timer was actually broken).
  
      As of this commit we use an independent message slot for event timer,
      so that we could handle all of event timer messages in the interrupt
      handler directly.  Note, the message slot for event timer is still
      bind to the same interrupt vector as the other types of messages.
  
      Submitted by:       Jun Su <junsu microsoft com>
      Reviewed by:        sephe
      Discussed with: Jun Su <junsu microsoft com>, Dexuan Cui <decui microsoft com>
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5696
  
  297177
      hyperv/vmbus: Use taskqueue_fast for non-performance critical messages
  
      This gets rid of the per-cpu SWIs.
  
      Submitted by:       Jun Su <junsu microsoft com>
      Reviewed by:        Dexuan Cui <decui microsoft com>, sephe
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5215
  
  297178
      hyperv/vmbus: Remove NULL check for taskqueue_create_fast(M_WAITOK)
  
      Submitted by:       Jun Su <junsu microsoft com>
      Reviewed by:        Dexuan Cui <decui microsoft com>, sephe
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5215
  
  297221
      hyperv/vmbus: Create per-cpu fast taskqueue for msg handling
  
      Using one taskqueue does not work, since the EOM MSR must be written
      on the msg's owner CPU.
  
      Noticed by: Jun Su <junsu microsoft com>
      Discussed with:     Jun Su <junsu microsoft com>, Dexuan Cui <decui microsoft com>
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC

Modified:
  stable/10/sys/dev/hyperv/include/hyperv.h
  stable/10/sys/dev/hyperv/utilities/hv_kvp.c
  stable/10/sys/dev/hyperv/vmbus/hv_et.c
  stable/10/sys/dev/hyperv/vmbus/hv_hv.c
  stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
  stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h	Thu Jun 16 03:02:27 2016	(r301945)
+++ stable/10/sys/dev/hyperv/include/hyperv.h	Thu Jun 16 03:04:16 2016	(r301946)
@@ -124,6 +124,8 @@ typedef struct hv_guid {
 	 unsigned char data[16];
 } __packed hv_guid;
 
+int snprintf_hv_guid(char *, size_t, const hv_guid *);
+
 #define HV_NIC_GUID							\
 	.data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,	\
 		0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}

Modified: stable/10/sys/dev/hyperv/utilities/hv_kvp.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_kvp.c	Thu Jun 16 03:02:27 2016	(r301945)
+++ stable/10/sys/dev/hyperv/utilities/hv_kvp.c	Thu Jun 16 03:04:16 2016	(r301946)
@@ -304,28 +304,11 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(stru
 {
 	int err_ip, err_subnet, err_gway, err_dns, err_adap;
 	int UNUSED_FLAG = 1;
-	int guid_index;
 	struct hv_device *hv_dev;       /* GUID Data Structure */
 	hn_softc_t *sc;                 /* hn softc structure  */
 	char if_name[4];
-	unsigned char guid_instance[40];
-	char *guid_data = NULL;
 	char buf[39];
 
-	struct guid_extract {
-		char	a1[2];
-		char	a2[2];
-		char	a3[2];
-		char	a4[2];
-		char	b1[2];
-		char	b2[2];
-		char	c1[2];
-		char	c2[2];
-		char	d[4];
-		char	e[12];
-	};
-
-	struct guid_extract *id;
 	device_t *devs;
 	int devcnt;
 
@@ -352,17 +335,7 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(stru
 			/* Trying to find GUID of Network Device */
 			hv_dev = sc->hn_dev_obj;
 
-			for (guid_index = 0; guid_index < 16; guid_index++) {
-				sprintf(&guid_instance[guid_index * 2], "%02x",
-				    hv_dev->device_id.data[guid_index]);
-			}
-
-			guid_data = (char *)guid_instance;
-			id = (struct guid_extract *)guid_data;
-			snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}",
-			    id->a4, id->a3, id->a2, id->a1,
-			    id->b2, id->b1, id->c2, id->c1, id->d, id->e);
-			guid_data = NULL;
+			snprintf_hv_guid(buf, sizeof(buf), &hv_dev->device_id);
 			sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt]));
 
 			if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) {

Modified: stable/10/sys/dev/hyperv/vmbus/hv_et.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_et.c	Thu Jun 16 03:02:27 2016	(r301945)
+++ stable/10/sys/dev/hyperv/vmbus/hv_et.c	Thu Jun 16 03:04:16 2016	(r301946)
@@ -60,7 +60,7 @@ hv_et_start(struct eventtimer *et, sbint
 
 	timer_cfg.as_uint64 = 0;
 	timer_cfg.auto_enable = 1;
-	timer_cfg.sintx = HV_VMBUS_MESSAGE_SINT;
+	timer_cfg.sintx = HV_VMBUS_TIMER_SINT;
 
 	periodticks[curcpu] = sbintime2tick(periodtime);
 	if (firsttime == 0)

Modified: stable/10/sys/dev/hyperv/vmbus/hv_hv.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_hv.c	Thu Jun 16 03:02:27 2016	(r301945)
+++ stable/10/sys/dev/hyperv/vmbus/hv_hv.c	Thu Jun 16 03:04:16 2016	(r301946)
@@ -370,6 +370,9 @@ hv_vmbus_synic_init(void *arg)
 	wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
 	    shared_sint.as_uint64_t);
 
+	wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT,
+	    shared_sint.as_uint64_t);
+
 	/* Enable the global synic bit */
 	sctrl.as_uint64_t = rdmsr(HV_X64_MSR_SCONTROL);
 	sctrl.u.enable = 1;
@@ -406,12 +409,23 @@ void hv_vmbus_synic_cleanup(void *arg)
 	shared_sint.u.masked = 1;
 
 	/*
-	 * Disable the interrupt
+	 * Disable the interrupt 0
 	 */
 	wrmsr(
 	    HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
 	    shared_sint.as_uint64_t);
 
+	shared_sint.as_uint64_t = rdmsr(
+	    HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT);
+
+	shared_sint.u.masked = 1;
+
+	/*
+	 * Disable the interrupt 1
+	 */
+	wrmsr(
+	    HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT,
+	    shared_sint.as_uint64_t);
 	simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
 	simp.u.simp_enabled = 0;
 	simp.u.base_simp_gpa = 0;

Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Thu Jun 16 03:02:27 2016	(r301945)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c	Thu Jun 16 03:04:16 2016	(r301946)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/pcpu.h>
 #include <machine/apicvar.h>
 
+#include <dev/hyperv/include/hyperv.h>
 #include "hv_vmbus_priv.h"
 
 #include <contrib/dev/acpica/include/acpi.h>
@@ -75,7 +76,7 @@ static char *vmbus_ids[] = { "VMBUS", NU
  * the hypervisor.
  */
 static void
-vmbus_msg_swintr(void *arg)
+vmbus_msg_swintr(void *arg, int pending __unused)
 {
 	int 			cpu;
 	void*			page_addr;
@@ -178,12 +179,15 @@ hv_vmbus_isr(struct trapframe *frame)
 
 	/* Check if there are actual msgs to be process */
 	page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
-	msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
+	msg = (hv_vmbus_message*) page_addr + HV_VMBUS_TIMER_SINT;
 
 	/* we call eventtimer process the message */
 	if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
 		msg->header.message_type = HV_MESSAGE_TYPE_NONE;
 
+		/* call intrrupt handler of event timer */
+		hv_et_intr(frame);
+
 		/*
 		 * Make sure the write to message_type (ie set to
 		 * HV_MESSAGE_TYPE_NONE) happens before we read the
@@ -204,12 +208,12 @@ hv_vmbus_isr(struct trapframe *frame)
 			 */
 			wrmsr(HV_X64_MSR_EOM, 0);
 		}
-		hv_et_intr(frame);
-		return (FILTER_HANDLED);
 	}
 
+	msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
 	if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
-		swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0);
+		taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[cpu],
+		    &hv_vmbus_g_context.hv_msg_task[cpu]);
 	}
 
 	return (FILTER_HANDLED);
@@ -287,6 +291,23 @@ vmbus_write_ivar(
 	return (ENOENT);
 }
 
+static int
+vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
+{
+	char guidbuf[40];
+	struct hv_device *dev_ctx = device_get_ivars(child);
+
+	strlcat(buf, "classid=", buflen);
+	snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->class_id);
+	strlcat(buf, guidbuf, buflen);
+
+	strlcat(buf, " deviceid=", buflen);
+	snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->device_id);
+	strlcat(buf, guidbuf, buflen);
+
+	return (0);
+}
+
 struct hv_device*
 hv_vmbus_child_device_create(
 	hv_guid		type,
@@ -308,15 +329,17 @@ hv_vmbus_child_device_create(
 	return (child_dev);
 }
 
-static void
-print_dev_guid(struct hv_device *dev)
+int
+snprintf_hv_guid(char *buf, size_t sz, const hv_guid *guid)
 {
-	int i;
-	unsigned char guid_name[100];
-	for (i = 0; i < 32; i += 2)
-		sprintf(&guid_name[i], "%02x", dev->class_id.data[i / 2]);
-	if(bootverbose)
-		printf("VMBUS: Class ID: %s\n", guid_name);
+	int cnt;
+	const unsigned char *d = guid->data;
+
+	cnt = snprintf(buf, sz,
+		"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
+		d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+	return (cnt);
 }
 
 int
@@ -325,8 +348,11 @@ hv_vmbus_child_device_register(struct hv
 	device_t child;
 	int ret = 0;
 
-	print_dev_guid(child_dev);
-
+	if (bootverbose) {
+		char name[40];
+		snprintf_hv_guid(name, sizeof(name), &child_dev->class_id);
+		printf("VMBUS: Class ID: %s\n", name);
+	}
 
 	child = device_add_child(vmbus_devp, NULL, -1);
 	child_dev->device = child;
@@ -506,9 +532,6 @@ vmbus_bus_init(void)
 	setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
 
 	CPU_FOREACH(j) {
-		hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
-		hv_vmbus_g_context.msg_swintr[j] = NULL;
-
 		snprintf(buf, sizeof(buf), "cpu%d:hyperv", j);
 		intrcnt_add(buf, &hv_vmbus_intr_cpu[j]);
 
@@ -527,11 +550,6 @@ vmbus_bus_init(void)
 		 */
 		hv_vmbus_g_context.hv_event_queue[j] = taskqueue_create_fast("hyperv event", M_WAITOK,
 			taskqueue_thread_enqueue, &hv_vmbus_g_context.hv_event_queue[j]);
-		if (hv_vmbus_g_context.hv_event_queue[j] == NULL) {
-			if (bootverbose)
-				printf("VMBUS: failed to setup taskqueue\n");
-			goto cleanup1;
-		}
 		taskqueue_start_threads(&hv_vmbus_g_context.hv_event_queue[j], 1, PI_NET,
 			"hvevent%d", j);
 
@@ -541,29 +559,20 @@ vmbus_bus_init(void)
 		taskqueue_drain(hv_vmbus_g_context.hv_event_queue[j], &cpuset_task);
 
 		/*
-		 * Setup software interrupt thread and handler for msg handling.
+		 * Setup per-cpu tasks and taskqueues to handle msg.
 		 */
-		ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j],
-		    "hv_msg", vmbus_msg_swintr, (void *)(long)j, SWI_CLOCK, 0,
-		    &hv_vmbus_g_context.msg_swintr[j]);
-		if (ret) {
-			if(bootverbose)
-				printf("VMBUS: failed to setup msg swi for "
-				    "cpu %d\n", j);
-			goto cleanup1;
-		}
+		hv_vmbus_g_context.hv_msg_tq[j] = taskqueue_create_fast(
+		    "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
+		    &hv_vmbus_g_context.hv_msg_tq[j]);
+		taskqueue_start_threads(&hv_vmbus_g_context.hv_msg_tq[j], 1, PI_NET,
+		    "hvmsg%d", j);
+		TASK_INIT(&hv_vmbus_g_context.hv_msg_task[j], 0,
+		    vmbus_msg_swintr, (void *)(long)j);
 
-		/*
-		 * Bind the swi thread to the cpu.
-		 */
-		ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j],
-		    j);
-		if (ret) {
-			if(bootverbose)
-				printf("VMBUS: failed to bind msg swi thread "
-				    "to cpu %d\n", j);
-			goto cleanup1;
-		}
+		CPU_SETOF(j, &cpu_mask);
+		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task, &cpu_mask);
+		taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[j], &cpuset_task);
+		taskqueue_drain(hv_vmbus_g_context.hv_msg_tq[j], &cpuset_task);
 
 		/*
 		 * Prepare the per cpu msg and event pages to be called on each cpu.
@@ -603,11 +612,10 @@ vmbus_bus_init(void)
 	 * remove swi and vmbus callback vector;
 	 */
 	CPU_FOREACH(j) {
-		if (hv_vmbus_g_context.hv_event_queue[j] != NULL)
+		if (hv_vmbus_g_context.hv_event_queue[j] != NULL) {
 			taskqueue_free(hv_vmbus_g_context.hv_event_queue[j]);
-		if (hv_vmbus_g_context.msg_swintr[j] != NULL)
-			swi_remove(hv_vmbus_g_context.msg_swintr[j]);
-		hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;	
+			hv_vmbus_g_context.hv_event_queue[j] = NULL;
+		}
 	}
 
 	vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
@@ -672,11 +680,10 @@ vmbus_bus_exit(void)
 
 	/* remove swi */
 	CPU_FOREACH(i) {
-		if (hv_vmbus_g_context.hv_event_queue[i] != NULL)
+		if (hv_vmbus_g_context.hv_event_queue[i] != NULL) {
 			taskqueue_free(hv_vmbus_g_context.hv_event_queue[i]);
-		if (hv_vmbus_g_context.msg_swintr[i] != NULL)
-			swi_remove(hv_vmbus_g_context.msg_swintr[i]);
-		hv_vmbus_g_context.hv_msg_intr_event[i] = NULL;	
+			hv_vmbus_g_context.hv_event_queue[i] = NULL;
+		}
 	}
 
 	vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
@@ -741,6 +748,7 @@ static device_method_t vmbus_methods[] =
 	DEVMETHOD(bus_print_child, bus_generic_print_child),
 	DEVMETHOD(bus_read_ivar, vmbus_read_ivar),
 	DEVMETHOD(bus_write_ivar, vmbus_write_ivar),
+	DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str),
 
 	{ 0, 0 } };
 

Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Thu Jun 16 03:02:27 2016	(r301945)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Thu Jun 16 03:04:16 2016	(r301946)
@@ -181,7 +181,8 @@ enum {
 	HV_VMBUS_EVENT_PORT_ID		= 2,
 	HV_VMBUS_MONITOR_CONNECTION_ID	= 3,
 	HV_VMBUS_MONITOR_PORT_ID	= 3,
-	HV_VMBUS_MESSAGE_SINT		= 2
+	HV_VMBUS_MESSAGE_SINT		= 2,
+	HV_VMBUS_TIMER_SINT		= 4,
 };
 
 #define HV_PRESENT_BIT		0x80000000
@@ -204,8 +205,8 @@ typedef struct {
 	 * event and msg handling.
 	 */
 	struct taskqueue		*hv_event_queue[MAXCPU];
-	struct intr_event		*hv_msg_intr_event[MAXCPU];
-	void				*msg_swintr[MAXCPU];
+	struct taskqueue		*hv_msg_tq[MAXCPU];
+	struct task			hv_msg_task[MAXCPU];
 	/*
 	 * Host use this vector to intrrupt guest for vmbus channel
 	 * event and msg.



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