Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jan 2017 03:38:41 +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: r311743 - in head/sys/dev/hyperv: include utilities vmbus vmbus/amd64
Message-ID:  <201701090338.v093cf9t047600@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Mon Jan  9 03:38:41 2017
New Revision: 311743
URL: https://svnweb.freebsd.org/changeset/base/311743

Log:
  hyperv: Add method to read 64bit Hyper-V specific time value.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D9057

Modified:
  head/sys/dev/hyperv/include/hyperv.h
  head/sys/dev/hyperv/utilities/vmbus_timesync.c
  head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
  head/sys/dev/hyperv/vmbus/hyperv.c
  head/sys/dev/hyperv/vmbus/vmbus_et.c

Modified: head/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- head/sys/dev/hyperv/include/hyperv.h	Mon Jan  9 03:21:21 2017	(r311742)
+++ head/sys/dev/hyperv/include/hyperv.h	Mon Jan  9 03:38:41 2017	(r311743)
@@ -79,9 +79,17 @@ struct hyperv_guid {
 
 #define HYPERV_GUID_STRLEN		40
 
-int		hyperv_guid2str(const struct hyperv_guid *, char *, size_t);
+typedef uint64_t			(*hyperv_tc64_t)(void);
 
-extern u_int	hyperv_features;	/* CPUID_HV_MSR_ */
+int			hyperv_guid2str(const struct hyperv_guid *, char *,
+			    size_t);
+
+/*
+ * hyperv_tc64 could be NULL, if there were no suitable Hyper-V
+ * specific timecounter.
+ */
+extern hyperv_tc64_t	hyperv_tc64;
+extern u_int		hyperv_features;	/* CPUID_HV_MSR_ */
 
 #endif	/* _KERNEL */
 

Modified: head/sys/dev/hyperv/utilities/vmbus_timesync.c
==============================================================================
--- head/sys/dev/hyperv/utilities/vmbus_timesync.c	Mon Jan  9 03:21:21 2017	(r311742)
+++ head/sys/dev/hyperv/utilities/vmbus_timesync.c	Mon Jan  9 03:38:41 2017	(r311743)
@@ -52,8 +52,7 @@ __FBSDID("$FreeBSD$");
 	VMBUS_ICVER_LE(VMBUS_IC_VERSION(4, 0), (sc)->ic_msgver)
 
 #define VMBUS_TIMESYNC_DORTT(sc)	\
-	(VMBUS_TIMESYNC_MSGVER4((sc)) &&\
-	 (hyperv_features & CPUID_HV_MSR_TIME_REFCNT))
+	(VMBUS_TIMESYNC_MSGVER4((sc)) && hyperv_tc64 != NULL)
 
 static int			vmbus_timesync_probe(device_t);
 static int			vmbus_timesync_attach(device_t);
@@ -117,7 +116,7 @@ vmbus_timesync(struct vmbus_ic_softc *sc
 	uint64_t hv_ns, vm_ns, rtt = 0;
 
 	if (VMBUS_TIMESYNC_DORTT(sc))
-		rtt = rdmsr(MSR_HV_TIME_REF_COUNT) - sent_tc;
+		rtt = hyperv_tc64() - sent_tc;
 
 	hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE + rtt) * HYPERV_TIMER_NS_FACTOR;
 	nanotime(&vm_ts);

Modified: head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c	Mon Jan  9 03:21:21 2017	(r311742)
+++ head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c	Mon Jan  9 03:38:41 2017	(r311743)
@@ -133,8 +133,8 @@ hyperv_tsc_vdso_timehands(struct vdso_ti
 }
 
 #define HYPERV_TSC_TIMECOUNT(fence)					\
-static u_int								\
-hyperv_tsc_timecount_##fence(struct timecounter *tc)			\
+static uint64_t								\
+hyperv_tc64_tsc_##fence(void)						\
 {									\
 	struct hyperv_reftsc *tsc_ref = hyperv_ref_tsc.tsc_ref;		\
 	uint32_t seq;							\
@@ -162,6 +162,13 @@ hyperv_tsc_timecount_##fence(struct time
 	/* Fallback to the generic timecounter, i.e. rdmsr. */		\
 	return (rdmsr(MSR_HV_TIME_REF_COUNT));				\
 }									\
+									\
+static u_int								\
+hyperv_tsc_timecount_##fence(struct timecounter *tc __unused)		\
+{									\
+									\
+	return (hyperv_tc64_tsc_##fence());				\
+}									\
 struct __hack
 
 HYPERV_TSC_TIMECOUNT(lfence);
@@ -170,6 +177,7 @@ HYPERV_TSC_TIMECOUNT(mfence);
 static void
 hyperv_tsc_tcinit(void *dummy __unused)
 {
+	hyperv_tc64_t tc64 = NULL;
 	uint64_t val, orig;
 
 	if ((hyperv_features &
@@ -182,11 +190,13 @@ hyperv_tsc_tcinit(void *dummy __unused)
 	case CPU_VENDOR_AMD:
 		hyperv_tsc_timecounter.tc_get_timecount =
 		    hyperv_tsc_timecount_mfence;
+		tc64 = hyperv_tc64_tsc_mfence;
 		break;
 
 	case CPU_VENDOR_INTEL:
 		hyperv_tsc_timecounter.tc_get_timecount =
 		    hyperv_tsc_timecount_lfence;
+		tc64 = hyperv_tc64_tsc_lfence;
 		break;
 
 	default:
@@ -211,6 +221,10 @@ hyperv_tsc_tcinit(void *dummy __unused)
 	/* Register "enlightened" timecounter. */
 	tc_init(&hyperv_tsc_timecounter);
 
+	/* Install 64 bits timecounter method for other modules to use. */
+	KASSERT(tc64 != NULL, ("tc64 is not set"));
+	hyperv_tc64 = tc64;
+
 	/* Add device for mmap(2). */
 	make_dev(&hyperv_tsc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0444,
 	    HYPERV_REFTSC_DEVNAME);

Modified: head/sys/dev/hyperv/vmbus/hyperv.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hyperv.c	Mon Jan  9 03:21:21 2017	(r311742)
+++ head/sys/dev/hyperv/vmbus/hyperv.c	Mon Jan  9 03:38:41 2017	(r311743)
@@ -77,6 +77,8 @@ u_int				hyperv_recommends;
 static u_int			hyperv_pm_features;
 static u_int			hyperv_features3;
 
+hyperv_tc64_t			hyperv_tc64;
+
 static struct timecounter	hyperv_timecounter = {
 	.tc_get_timecount	= hyperv_get_timecount,
 	.tc_poll_pps		= NULL,
@@ -96,6 +98,13 @@ hyperv_get_timecount(struct timecounter 
 	return rdmsr(MSR_HV_TIME_REF_COUNT);
 }
 
+static uint64_t
+hyperv_tc64_rdmsr(void)
+{
+
+	return (rdmsr(MSR_HV_TIME_REF_COUNT));
+}
+
 uint64_t
 hypercall_post_message(bus_addr_t msg_paddr)
 {
@@ -232,6 +241,12 @@ hyperv_init(void *dummy __unused)
 	if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) {
 		/* Register Hyper-V timecounter */
 		tc_init(&hyperv_timecounter);
+
+		/*
+		 * Install 64 bits timecounter method for other modules
+		 * to use.
+		 */
+		hyperv_tc64 = hyperv_tc64_rdmsr;
 	}
 }
 SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init,

Modified: head/sys/dev/hyperv/vmbus/vmbus_et.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_et.c	Mon Jan  9 03:21:21 2017	(r311742)
+++ head/sys/dev/hyperv/vmbus/vmbus_et.c	Mon Jan  9 03:38:41 2017	(r311743)
@@ -48,13 +48,10 @@ __FBSDID("$FreeBSD$");
 	 MSR_HV_STIMER_CFG_SINT_MASK)
 
 /*
- * Two additionally required features:
+ * Additionally required feature:
  * - SynIC is needed for interrupt generation.
- * - Time reference counter is needed to set ABS reference count to
- *   STIMER0_COUNT.
  */
-#define CPUID_HV_ET_MASK		(CPUID_HV_MSR_TIME_REFCNT |	\
-					 CPUID_HV_MSR_SYNIC |		\
+#define CPUID_HV_ET_MASK		(CPUID_HV_MSR_SYNIC |		\
 					 CPUID_HV_MSR_SYNTIMER)
 
 static void			vmbus_et_identify(driver_t *, device_t);
@@ -102,7 +99,7 @@ vmbus_et_start(struct eventtimer *et __u
 {
 	uint64_t current;
 
-	current = rdmsr(MSR_HV_TIME_REF_COUNT);
+	current = hyperv_tc64();
 	current += hyperv_sbintime2count(first);
 	wrmsr(MSR_HV_STIMER0_COUNT, current);
 
@@ -131,7 +128,8 @@ vmbus_et_identify(driver_t *driver, devi
 {
 	if (device_get_unit(parent) != 0 ||
 	    device_find_child(parent, VMBUS_ET_NAME, -1) != NULL ||
-	    (hyperv_features & CPUID_HV_ET_MASK) != CPUID_HV_ET_MASK)
+	    (hyperv_features & CPUID_HV_ET_MASK) != CPUID_HV_ET_MASK ||
+	    hyperv_tc64 == NULL)
 		return;
 
 	device_add_child(parent, VMBUS_ET_NAME, -1);
@@ -187,9 +185,8 @@ vmbus_et_attach(device_t dev)
 	vmbus_et.et_start = vmbus_et_start;
 
 	/*
-	 * Delay a bit to make sure that MSR_HV_TIME_REF_COUNT will
-	 * not return 0, since writing 0 to STIMER0_COUNT will disable
-	 * STIMER0.
+	 * Delay a bit to make sure that hyperv_tc64 will not return 0,
+	 * since writing 0 to STIMER0_COUNT will disable STIMER0.
 	 */
 	DELAY(100);
 	smp_rendezvous(NULL, vmbus_et_config, NULL, NULL);



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